"lib/features/splash/splash_screen_viewmodel.dart" did not exist on "928c36607368ad881adc0b6a757fe1c160fad459"
Commit 6b980613 authored by DatHV's avatar DatHV
Browse files

update project structure

parent bfff9e47
# Giải thích chi tiết về Cấu trúc Mới
## Tổng quan
Cấu trúc mới được thiết kế theo **Clean Architecture** kết hợp với **Feature-based organization**, giúp code dễ maintain, scale và test hơn.
## Kiến trúc 3 Layers
### 1. Core Layer (`lib/core/`)
**Mục đích**: Chứa các thành phần được dùng chung trên toàn bộ app, không phụ thuộc vào business logic cụ thể.
#### `core/config/`
- **Chức năng**: Tất cả các configuration files
- **Files**:
- `api_paths.dart` - API endpoints
- `constants.dart` - App constants
- `device_info.dart` - Device information
- `env_loader.dart` - Environment loader
- **Lý do**: Tập trung tất cả configs ở một nơi, dễ quản lý và thay đổi
#### `core/initialization/`
- **Chức năng**: Khởi tạo app và các services
- **Files**:
- `app_initializer.dart` - Main app initialization
- `web_app_initializer.dart` - Web-specific initialization
- `deep_link_service.dart` - Deep linking
- **Lý do**: Tách biệt logic khởi tạo, dễ test và maintain
#### `core/network/`
- **Chức năng**: Network layer với HTTP client, interceptors, API clients
- **Cấu trúc**:
```
network/
├── api/ # API clients (affiliate, game, location, etc.)
├── interceptor/ # HTTP interceptors (auth, logger, error)
├── dio_http_service.dart
├── error_mapper.dart
└── restful_api_client.dart
```
- **Lý do**: Tập trung tất cả network logic, dễ mock khi test
#### `core/storage/`
- **Chức năng**: Local storage và preferences
- **Files**:
- `data_preference.dart` - SharedPreferences wrapper
- `contact_storage_service.dart` - Contact storage
- `point/` - Point management storage
- **Lý do**: Tách biệt storage logic, dễ thay đổi implementation
#### `core/services/`
- **Chức năng**: Core business services
- **Cấu trúc**:
```
services/
├── auth/
│ ├── login_service.dart
│ ├── logout_service.dart
│ └── token_refresh_service.dart
└── notification/
```
- **Lý do**: Services được dùng chung, không thuộc về feature cụ thể
#### `core/platform/`
- **Chức năng**: Platform-specific code
- **Cấu trúc**:
```
platform/
├── web/ # Web-specific (x-app-sdk, web helpers)
├── permission/ # Permissions (biometric, etc.)
└── firebase/ # Firebase integration
```
- **Lý do**: Tách biệt platform code, dễ maintain cho từng platform
#### `core/base/`
- **Chức năng**: Base classes cho screens, viewmodels, models
- **Files**:
- `base_screen.dart` - Base class cho screens
- `base_view_model.dart` - Base class cho viewmodels
- `base_response_model.dart` - Base class cho API responses
- `basic_state.dart` - Base state management
- **Lý do**: DRY principle, giảm code duplication
#### `core/utils/`
- **Chức năng**: Utilities và extensions
- **Cấu trúc**:
```
utils/
├── validation_utils.dart
├── direction_google_map.dart
├── router_gage.dart
└── extensions/ # Extension methods
├── collection_extension.dart
├── color_extension.dart
├── date_format.dart
└── ...
```
- **Lý do**: Gộp `shared/``utils/` lại, tránh confusion
#### `core/navigation/`
- **Chức năng**: Navigation và routing
- **Files**:
- `app_navigator.dart` - Main navigator
- `deferred_routes.dart` - Lazy loading routes
- `directional_action_type.dart` - Direction actions
- `directional_screen.dart` - Direction screens
- **Lý do**: Gộp `deferred/``directional/` lại, tất cả navigation ở một nơi
#### `core/theme/`
- **Chức năng**: Theme, colors, styles, images
- **Files**:
- `colors.dart` (từ `base_color.dart`)
- `text_styles.dart` (từ `text_style.dart`)
- `button_styles.dart` (từ `button_style.dart`)
- `images.dart` (từ `define_image.dart`)
- **Lý do**: Đổi tên từ `resources/` sang `theme/` cho rõ ràng hơn
#### `core/widgets/`
- **Chức năng**: Core reusable widgets
- **Files**:
- `app_loading.dart`
- `alert/` - Alert widgets
- `custom_app_bar.dart`
- `custom_empty_widget.dart`
- Và các widgets dùng chung khác
- **Lý do**: Widgets được dùng chung trên toàn app
---
### 2. Features Layer (`lib/features/`)
**Mục đích**: Mỗi feature là một module độc lập, có thể phát triển và test riêng biệt.
#### Cấu trúc mỗi Feature
Mỗi feature có 3 layers:
```
feature_name/
├── data/ # Data layer (outermost)
│ ├── models/ # Data models (API responses)
│ ├── repositories/ # Repository implementations
│ └── datasources/ # Remote/Local data sources
├── domain/ # Domain layer (middle)
│ ├── entities/ # Business entities
│ └── usecases/ # Use cases (business logic)
└── presentation/ # Presentation layer (innermost)
├── screens/ # UI screens
├── viewmodels/ # ViewModels (state management)
└── widgets/ # Feature-specific widgets
```
#### Ví dụ: Auth Feature
```
features/auth/
├── data/
│ ├── models/
│ │ ├── login_token_response_model.dart # API response model
│ │ ├── profile_response_model.dart
│ │ └── user_agreement_model.dart
│ ├── repositories/
│ │ └── auth_repository_impl.dart # Implements domain repository
│ └── datasources/
│ ├── auth_remote_datasource.dart # API calls
│ └── auth_local_datasource.dart # Local storage
├── domain/
│ ├── entities/
│ │ └── user.dart # Business entity (pure Dart)
│ ├── repositories/
│ │ └── auth_repository.dart # Repository interface
│ └── usecases/
│ ├── login_usecase.dart # Business logic
│ ├── logout_usecase.dart
│ └── get_profile_usecase.dart
└── presentation/
├── screens/
│ ├── login/
│ │ ├── login_screen.dart
│ │ └── login_viewmodel.dart
│ ├── otp/
│ └── create_pass/
└── widgets/
└── auth_form_widget.dart
```
**Lợi ích**:
- **Separation of concerns**: Mỗi layer có trách nhiệm riêng
- **Testability**: Có thể test từng layer độc lập
- **Dependency rule**: Inner layers không phụ thuộc outer layers
- **Reusability**: Domain layer có thể reuse cho web/mobile
#### Feature Organization
**1. Auth Feature** (`features/auth/`)
- Login, OTP, Create password
- Authentication logic
**2. Home Feature** (`features/home/`)
- Home screen (40 files)
- Dashboard, main content
**3. Voucher Feature** (`features/voucher/`)
- Voucher screens (46 files)
- Voucher management
**4. Transaction Feature** (`features/transaction/`)
- Transaction screens (25 files)
- Transaction history, details
**5. Campaign Feature** (`features/campaign/`)
- Campaign 7day
- Quiz campaign
- Register campaign
- Invite friend campaign
**6. Payment Feature** (`features/payment/`)
- Electric payment
- Mobile card
- Topup
- Traffic service
**7. Point Feature** (`features/point/`)
- History point
- History point cashback
- Daily checkin
**8. Profile Feature** (`features/profile/`)
- Personal
- Settings
- Change password
- Delete account
- Biometric
**9. Notification Feature** (`features/notification/`)
- Notification screens (12 files)
**10. Membership Feature** (`features/membership/`)
- Membership screens (10 files)
**11. Affiliate Feature** (`features/affiliate/`)
- Affiliate
- Affiliate brand detail
**12. Game Feature** (`features/game/`)
- Game
- VPlay game center
**13. Support Feature** (`features/support/`)
- Support
- FAQs
- News
**14. Common Feature** (`features/common/`)
- Splash
- Onboarding
- Webview
- QR code
- Popup manager
- Main tab screen
---
### 3. Shared Layer (`lib/shared/`)
**Mục đích**: Widgets và components được dùng chung giữa các features.
```
shared/
└── widgets/
├── custom_navigation_bar.dart
├── custom_point_text_tag.dart
└── ...
```
**Lý do**: Khác với `core/widgets/`, `shared/widgets/` là các widgets được dùng bởi nhiều features nhưng không phải core functionality.
---
## Dependency Flow
```
Presentation Layer (UI)
↓ depends on
Domain Layer (Business Logic)
↓ depends on
Data Layer (API, Storage)
```
**Quy tắc**:
- Presentation chỉ phụ thuộc Domain
- Domain không phụ thuộc Presentation hay Data
- Data phụ thuộc Domain (implements interfaces)
---
## So sánh với cấu trúc cũ
### Cấu trúc cũ:
```
lib/
├── screen/ # 375+ files trong 1 thư mục
├── model/ # Chỉ có auth models
├── networking/ # Network layer
├── services/ # Services rời rạc
├── shared/ # Không rõ mục đích
├── utils/ # Trùng với shared
└── ...
```
**Vấn đề**:
- Khó tìm code
- Khó maintain
- Khó test
- Khó scale
### Cấu trúc mới:
```
lib/
├── core/ # Core functionality
│ ├── config/
│ ├── network/
│ ├── storage/
│ └── ...
├── features/ # Feature modules
│ ├── auth/
│ │ ├── data/
│ │ ├── domain/
│ │ └── presentation/
│ └── ...
└── shared/ # Shared widgets
```
**Lợi ích**:
- ✅ Dễ tìm code (theo feature)
- ✅ Dễ maintain (mỗi feature độc lập)
- ✅ Dễ test (test từng layer)
- ✅ Dễ scale (thêm feature mới dễ dàng)
---
## Migration Strategy
### Phase 1: Core Reorganization (Low Risk)
- Gộp configs, utils, navigation
- Không ảnh hưởng business logic
- Dễ rollback
### Phase 2: Network & Services (Medium Risk)
- Di chuyển networking và services
- Cần update imports
- Test kỹ API calls
### Phase 3: Feature-based (High Risk)
- Di chuyển screens theo features
- Tạo data/domain/presentation layers
- Cần test toàn bộ app
---
## Best Practices
1. **Mỗi feature độc lập**: Có thể develop và test riêng
2. **Dependency injection**: Dùng GetX hoặc provider
3. **Repository pattern**: Tách biệt data source và business logic
4. **Use cases**: Mỗi business action là một use case
5. **Entities**: Pure Dart classes, không phụ thuộc framework
---
## Ví dụ Migration
### Trước (Cấu trúc cũ):
```dart
// lib/screen/login/login_screen.dart
import 'package:mypoint_flutter_app/networking/restful_api_client.dart';
import 'package:mypoint_flutter_app/model/auth/login_token_response_model.dart';
import 'package:mypoint_flutter_app/services/login_service.dart';
```
### Sau (Cấu trúc mới):
```dart
// lib/features/auth/presentation/screens/login/login_screen.dart
import 'package:mypoint_flutter_app/features/auth/domain/usecases/login_usecase.dart';
import 'package:mypoint_flutter_app/features/auth/domain/entities/user.dart';
```
**Lợi ích**:
- Presentation không phụ thuộc trực tiếp vào API
- Dễ test (mock use case)
- Dễ thay đổi implementation
---
## Kết luận
Cấu trúc mới giúp:
- ✅ Code organization tốt hơn
- ✅ Dễ maintain và scale
- ✅ Dễ test
- ✅ Team collaboration tốt hơn
- ✅ Tuân thủ Clean Architecture principles
# Migration Guide - Chuyển đổi sang Cấu trúc Mới
## Tổng quan
Guide này hướng dẫn từng bước để migrate từ cấu trúc cũ sang cấu trúc mới theo Clean Architecture.
## ⚠️ Lưu ý quan trọng
1. **Backup trước khi bắt đầu**: Script sẽ tự động tạo backup, nhưng nên commit code trước
2. **Chạy từng phase**: Không chạy tất cả phases cùng lúc
3. **Test sau mỗi phase**: Đảm bảo app vẫn hoạt động sau mỗi bước
4. **Update imports**: Sau mỗi phase, cần update imports
## Prerequisites
```bash
# Đảm bảo đã commit code
git status
git add .
git commit -m "Before migration to new structure"
```
## Phase 1: Core Reorganization (Low Risk)
### Mục tiêu
Tổ chức lại core layer: configs, utils, navigation, theme
### Các thay đổi
- `configs/``core/config/`
- `env_loader.dart``core/config/env_loader.dart`
- `core/app_initializer.dart``core/initialization/app_initializer.dart`
- `utils/` + `shared/``core/utils/`
- `extensions/``core/utils/extensions/`
- `deferred/` + `directional/``core/navigation/`
- `resources/``core/theme/` (và rename files)
### Các bước
#### Bước 1: Chạy migration script
```bash
./migrate_structure.sh phase1
```
#### Bước 2: Update imports
```bash
./update_imports.sh phase1
```
#### Bước 3: Update file references
Cần update các references trong code:
**Resources/Theme:**
```dart
// Trước
import 'package:mypoint_flutter_app/resources/base_color.dart';
final color = BaseColor.primary;
// Sau
import 'package:mypoint_flutter_app/core/theme/colors.dart';
final color = AppColors.primary; // Cần rename class nếu cần
```
**Configs:**
```dart
// Trước
import 'package:mypoint_flutter_app/configs/api_paths.dart';
// Sau
import 'package:mypoint_flutter_app/core/config/api_paths.dart';
```
#### Bước 4: Test
```bash
flutter pub get
flutter analyze
flutter run
```
#### Bước 5: Fix lỗi
- Kiểm tra các lỗi import
- Update các references còn sót
- Test lại app
---
## Phase 2: Network & Services (Medium Risk)
### Mục tiêu
Tổ chức lại network layer, services, storage, và platform code
### Các thay đổi
- `networking/``core/network/`
- `services/``core/services/auth/`
- `preference/``core/storage/`
- `web/``core/platform/web/`
- `permission/``core/platform/permission/`
- `firebase/``core/platform/firebase/`
### Các bước
#### Bước 1: Chạy migration script
```bash
./migrate_structure.sh phase2
```
#### Bước 2: Update imports
```bash
./update_imports.sh phase2
```
#### Bước 3: Update API client references
```dart
// Trước
import 'package:mypoint_flutter_app/networking/api/affiliate_api.dart';
// Sau
import 'package:mypoint_flutter_app/core/network/api/affiliate_api.dart';
```
#### Bước 4: Update service references
```dart
// Trước
import 'package:mypoint_flutter_app/services/login_service.dart';
// Sau
import 'package:mypoint_flutter_app/core/services/auth/login_service.dart';
```
#### Bước 5: Update storage references
```dart
// Trước
import 'package:mypoint_flutter_app/preference/data_preference.dart';
// Sau
import 'package:mypoint_flutter_app/core/storage/data_preference.dart';
```
#### Bước 6: Update platform references
```dart
// Trước
import 'package:mypoint_flutter_app/web/web_helper.dart';
// Sau
import 'package:mypoint_flutter_app/core/platform/web/web_helper.dart';
```
#### Bước 7: Test
```bash
flutter pub get
flutter analyze
flutter run
# Test API calls, services, storage
```
---
## Phase 3: Feature-based Organization (High Risk)
### Mục tiêu
Tổ chức screens theo features với data/domain/presentation layers
### ⚠️ Cảnh báo
Phase này **KHÔNG tự động hoàn toàn**. Cần:
- Di chuyển screens thủ công
- Tạo data/domain layers
- Refactor code để tuân thủ Clean Architecture
### Các bước
#### Bước 1: Tạo feature structure
```bash
./migrate_structure.sh phase3
```
Script sẽ tạo cấu trúc thư mục cho tất cả features nhưng **KHÔNG di chuyển files**.
#### Bước 2: Di chuyển screens thủ công
**Ví dụ: Auth Feature**
```bash
# Di chuyển login screens
mkdir -p lib/features/auth/presentation/screens/login
mv lib/screen/login/* lib/features/auth/presentation/screens/login/
# Di chuyển OTP screens
mkdir -p lib/features/auth/presentation/screens/otp
mv lib/screen/otp/* lib/features/auth/presentation/screens/otp/
# Di chuyển create_pass screens
mkdir -p lib/features/auth/presentation/screens/create_pass
mv lib/screen/create_pass/* lib/features/auth/presentation/screens/create_pass/
```
**Ví dụ: Home Feature**
```bash
# Di chuyển home screens
mkdir -p lib/features/home/presentation/screens
mv lib/screen/home/* lib/features/home/presentation/screens/
```
#### Bước 3: Di chuyển models
```bash
# Di chuyển auth models
mv lib/model/auth/* lib/features/auth/data/models/
```
#### Bước 4: Update imports trong screens
Cần update imports trong các files đã di chuyển:
```dart
// Trước (trong login_screen.dart)
import 'package:mypoint_flutter_app/model/auth/login_token_response_model.dart';
import 'package:mypoint_flutter_app/services/login_service.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client.dart';
// Sau
import 'package:mypoint_flutter_app/features/auth/data/models/login_token_response_model.dart';
import 'package:mypoint_flutter_app/core/services/auth/login_service.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client.dart';
```
#### Bước 5: Tạo Domain Layer (Optional nhưng khuyến nghị)
**Tạo entities:**
```dart
// lib/features/auth/domain/entities/user.dart
class User {
final String id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
}
```
**Tạo use cases:**
```dart
// lib/features/auth/domain/usecases/login_usecase.dart
class LoginUseCase {
final AuthRepository repository;
LoginUseCase(this.repository);
Future<Either<Failure, User>> call(LoginParams params) async {
return await repository.login(params.email, params.password);
}
}
```
**Tạo repository interface:**
```dart
// lib/features/auth/domain/repositories/auth_repository.dart
abstract class AuthRepository {
Future<Either<Failure, User>> login(String email, String password);
Future<Either<Failure, void>> logout();
}
```
#### Bước 6: Tạo Data Layer
**Tạo repository implementation:**
```dart
// lib/features/auth/data/repositories/auth_repository_impl.dart
class AuthRepositoryImpl implements AuthRepository {
final AuthRemoteDataSource remoteDataSource;
final AuthLocalDataSource localDataSource;
@override
Future<Either<Failure, User>> login(String email, String password) async {
try {
final response = await remoteDataSource.login(email, password);
return Right(response.toEntity());
} catch (e) {
return Left(ServerFailure(e.toString()));
}
}
}
```
#### Bước 7: Update routes
Cần update route definitions:
```dart
// Trước
GetPage(
name: '/login',
page: () => LoginScreen(),
)
// Sau
GetPage(
name: '/login',
page: () => const LoginScreen(), // Import từ features/auth
)
```
#### Bước 8: Test toàn bộ app
```bash
flutter pub get
flutter analyze
flutter test
flutter run
# Test tất cả features
```
---
## Checklist Migration
### Phase 1 Checklist
- [ ] Backup created
- [ ] Migration script chạy thành công
- [ ] Imports updated
- [ ] `flutter pub get` chạy thành công
- [ ] `flutter analyze` không có lỗi
- [ ] App chạy được
- [ ] Test các chức năng cơ bản
### Phase 2 Checklist
- [ ] Migration script chạy thành công
- [ ] Imports updated
- [ ] API calls hoạt động
- [ ] Services hoạt động
- [ ] Storage hoạt động
- [ ] Platform code hoạt động
- [ ] `flutter analyze` không có lỗi
- [ ] App chạy được
### Phase 3 Checklist
- [ ] Feature structures created
- [ ] Screens đã di chuyển
- [ ] Models đã di chuyển
- [ ] Imports updated
- [ ] Routes updated
- [ ] Domain layer created (optional)
- [ ] Data layer created (optional)
- [ ] `flutter analyze` không có lỗi
- [ ] App chạy được
- [ ] Tất cả features test thành công
---
## Rollback Plan
Nếu có vấn đề, có thể rollback:
```bash
# Restore từ backup
cp -r .migration_backup_YYYYMMDD_HHMMSS/lib/* lib/
# Hoặc từ git
git reset --hard HEAD
```
---
## Common Issues & Solutions
### Issue 1: Import errors
**Solution**: Chạy `./update_imports.sh phaseX` và kiểm tra lại
### Issue 2: Missing files
**Solution**: Kiểm tra backup folder, restore files cần thiết
### Issue 3: Circular dependencies
**Solution**: Refactor code để tránh circular imports
### Issue 4: Build errors
**Solution**:
```bash
flutter clean
flutter pub get
flutter pub upgrade
```
---
## Best Practices
1. **Commit sau mỗi phase**: Để dễ rollback nếu cần
2. **Test kỹ**: Test tất cả features sau mỗi phase
3. **Code review**: Review code sau mỗi phase
4. **Documentation**: Update documentation khi cần
5. **Team communication**: Thông báo team về changes
---
## Timeline ước tính
- **Phase 1**: 1-2 giờ (low risk)
- **Phase 2**: 2-4 giờ (medium risk)
- **Phase 3**: 1-2 tuần (high risk, cần refactor nhiều)
---
## Support
Nếu gặp vấn đề:
1. Kiểm tra backup folder
2. Review migration logs
3. Check import errors với `flutter analyze`
4. Rollback nếu cần
# Đề xuất Cấu trúc Project (Refactored)
## Phân tích vấn đề hiện tại
### Vấn đề:
1. **Thiếu tổ chức theo layer**: Không rõ ràng về Presentation, Domain, Data layers
2. **Thư mục rời rạc**: `shared/`, `utils/`, `deferred/`, `directional/` không rõ mục đích
3. **Model chỉ có auth**: Thiếu models cho các features khác
4. **Screen quá lớn**: 375+ files trong một thư mục, khó quản lý
5. **Services và Networking tách rời**: Không có mối liên kết rõ ràng
6. **Thiếu domain layer**: Không có entities, use cases, repositories pattern
## Cấu trúc đề xuất (Clean Architecture + Feature-based)
```
flutter_app_mypoint/
├── lib/
│ ├── main.dart # Entry point
│ │
│ ├── core/ # Core functionality (shared across features)
│ │ ├── config/ # Configuration
│ │ │ ├── api_paths.dart
│ │ │ ├── constants.dart
│ │ │ ├── device_info.dart
│ │ │ └── env_loader.dart
│ │ │
│ │ ├── initialization/ # App initialization
│ │ │ ├── app_initializer.dart
│ │ │ ├── web_app_initializer.dart
│ │ │ └── deep_link_service.dart
│ │ │
│ │ ├── network/ # Network layer
│ │ │ ├── api/ # API clients
│ │ │ │ ├── affiliate_api.dart
│ │ │ │ ├── game_api.dart
│ │ │ │ ├── location_api.dart
│ │ │ │ ├── notification_api.dart
│ │ │ │ ├── product_api.dart
│ │ │ │ └── website_api.dart
│ │ │ ├── interceptor/ # HTTP interceptors
│ │ │ │ ├── auth_interceptor.dart
│ │ │ │ ├── exception_interceptor.dart
│ │ │ │ ├── logger_interceptor.dart
│ │ │ │ ├── network_error_gate.dart
│ │ │ │ └── request_interceptor.dart
│ │ │ ├── dio_http_service.dart
│ │ │ ├── error_mapper.dart
│ │ │ └── restful_api_client.dart
│ │ │
│ │ ├── storage/ # Local storage
│ │ │ ├── data_preference.dart
│ │ │ ├── contact_storage_service.dart
│ │ │ └── point/
│ │ │ ├── point_manager.dart
│ │ │ └── header_home_model.dart
│ │ │
│ │ ├── services/ # Core services
│ │ │ ├── auth/
│ │ │ │ ├── login_service.dart
│ │ │ │ ├── logout_service.dart
│ │ │ │ └── token_refresh_service.dart
│ │ │ └── notification/
│ │ │ └── (notification services)
│ │ │
│ │ ├── platform/ # Platform-specific
│ │ │ ├── web/
│ │ │ │ ├── x_app_sdk_service.dart
│ │ │ │ ├── web_helper.dart
│ │ │ │ └── web_helper_web.dart
│ │ │ ├── permission/
│ │ │ │ └── biometric_manager.dart
│ │ │ └── firebase/
│ │ │ ├── firebase_options.dart
│ │ │ ├── push_notification.dart
│ │ │ └── push_setup.dart
│ │ │
│ │ ├── base/ # Base classes
│ │ │ ├── base_screen.dart
│ │ │ ├── base_view_model.dart
│ │ │ ├── base_response_model.dart
│ │ │ └── basic_state.dart
│ │ │
│ │ ├── utils/ # Utilities (merged shared + utils)
│ │ │ ├── validation_utils.dart
│ │ │ ├── direction_google_map.dart
│ │ │ ├── router_gage.dart
│ │ │ └── extensions/ # Extension methods
│ │ │ ├── collection_extension.dart
│ │ │ ├── color_extension.dart
│ │ │ ├── crypto.dart
│ │ │ ├── date_format.dart
│ │ │ ├── datetime_extensions.dart
│ │ │ ├── debouncer.dart
│ │ │ ├── num_extension.dart
│ │ │ └── string_extension.dart
│ │ │
│ │ ├── navigation/ # Navigation (merged deferred + directional)
│ │ │ ├── app_navigator.dart
│ │ │ ├── deferred_routes.dart
│ │ │ ├── directional_action_type.dart
│ │ │ └── directional_screen.dart
│ │ │
│ │ ├── theme/ # Theme & Resources (renamed from resources)
│ │ │ ├── colors.dart # base_color.dart
│ │ │ ├── text_styles.dart # text_style.dart
│ │ │ ├── button_styles.dart # button_style.dart
│ │ │ └── images.dart # define_image.dart
│ │ │
│ │ └── widgets/ # Core reusable widgets
│ │ ├── app_loading.dart
│ │ ├── alert/ # Alert widgets
│ │ ├── custom_app_bar.dart
│ │ ├── custom_empty_widget.dart
│ │ └── ... (other core widgets)
│ │
│ ├── features/ # Feature modules (organized by domain)
│ │ │
│ │ ├── auth/ # Authentication feature
│ │ │ ├── data/
│ │ │ │ ├── models/ # Data models
│ │ │ │ │ ├── login_token_response_model.dart
│ │ │ │ │ ├── profile_response_model.dart
│ │ │ │ │ └── ...
│ │ │ │ ├── repositories/ # Data repositories
│ │ │ │ │ └── auth_repository.dart
│ │ │ │ └── datasources/ # Data sources
│ │ │ │ └── auth_remote_datasource.dart
│ │ │ ├── domain/
│ │ │ │ ├── entities/ # Domain entities
│ │ │ │ │ └── user.dart
│ │ │ │ └── usecases/ # Use cases
│ │ │ │ ├── login_usecase.dart
│ │ │ │ └── logout_usecase.dart
│ │ │ └── presentation/
│ │ │ ├── screens/
│ │ │ │ ├── login/
│ │ │ │ ├── otp/
│ │ │ │ └── create_pass/
│ │ │ ├── viewmodels/
│ │ │ └── widgets/ # Feature-specific widgets
│ │ │
│ │ ├── home/ # Home feature
│ │ │ ├── data/
│ │ │ │ ├── models/
│ │ │ │ └── repositories/
│ │ │ ├── domain/
│ │ │ │ ├── entities/
│ │ │ │ └── usecases/
│ │ │ └── presentation/
│ │ │ ├── screens/
│ │ │ │ └── (40 files from home/)
│ │ │ ├── viewmodels/
│ │ │ └── widgets/
│ │ │
│ │ ├── voucher/ # Voucher feature
│ │ │ ├── data/
│ │ │ ├── domain/
│ │ │ └── presentation/
│ │ │ └── screens/ # (46 files from voucher/)
│ │ │
│ │ ├── transaction/ # Transaction feature
│ │ │ ├── data/
│ │ │ ├── domain/
│ │ │ └── presentation/
│ │ │ └── screens/ # (25 files from transaction/)
│ │ │
│ │ ├── campaign/ # Campaign features (merged)
│ │ │ ├── campaign7day/
│ │ │ ├── quiz_campaign/
│ │ │ ├── register_campaign/
│ │ │ └── invite_friend_campaign/
│ │ │
│ │ ├── payment/ # Payment features (merged)
│ │ │ ├── electric_payment/
│ │ │ ├── mobile_card/
│ │ │ ├── topup/
│ │ │ └── traffic_service/
│ │ │
│ │ ├── point/ # Point management
│ │ │ ├── history_point/
│ │ │ ├── history_point_cashback/
│ │ │ └── daily_checkin/
│ │ │
│ │ ├── profile/ # Profile & Settings
│ │ │ ├── personal/
│ │ │ ├── setting/
│ │ │ ├── change_pass/
│ │ │ ├── delete_account/
│ │ │ └── biometric/
│ │ │
│ │ ├── notification/ # Notification feature
│ │ │ └── presentation/
│ │ │ └── screens/ # (12 files from notification/)
│ │ │
│ │ ├── membership/ # Membership feature
│ │ │ └── presentation/
│ │ │ └── screens/ # (10 files from membership/)
│ │ │
│ │ ├── affiliate/ # Affiliate feature
│ │ │ ├── affiliate/
│ │ │ └── affiliate_brand_detail/
│ │ │
│ │ ├── game/ # Game features
│ │ │ ├── game/
│ │ │ └── vplay_game_center/
│ │ │
│ │ ├── support/ # Support features
│ │ │ ├── support/
│ │ │ ├── faqs/
│ │ │ └── news/
│ │ │
│ │ └── common/ # Common features
│ │ ├── splash/
│ │ ├── onboarding/
│ │ ├── webview/
│ │ ├── qr_code/
│ │ ├── popup_manager/
│ │ └── main_tab_screen/
│ │
│ └── shared/ # Shared across features (optional)
│ └── widgets/ # Shared widgets
│ ├── custom_navigation_bar.dart
│ ├── custom_point_text_tag.dart
│ └── ...
├── assets/ # (unchanged)
├── web/ # (unchanged)
├── android/ # (unchanged)
├── ios/ # (unchanged)
└── ... (other files unchanged)
```
## So sánh với cấu trúc hiện tại
### Cải thiện chính:
1. **Core layer rõ ràng**:
- Gộp `configs/` vào `core/config/`
- Gộp `shared/``utils/` vào `core/utils/`
- Gộp `deferred/``directional/` vào `core/navigation/`
- Đổi `resources/` thành `core/theme/` (rõ ràng hơn)
2. **Feature-based organization**:
- Chia `screen/` thành các feature modules
- Mỗi feature có cấu trúc: `data/`, `domain/`, `presentation/`
- Dễ scale và maintain
3. **Separation of concerns**:
- **Data layer**: Models, repositories, datasources
- **Domain layer**: Entities, use cases
- **Presentation layer**: Screens, viewmodels, widgets
4. **Grouping related features**:
- Campaign features → `campaign/`
- Payment features → `payment/`
- Point features → `point/`
- Profile features → `profile/`
## Migration Plan
### Phase 1: Reorganize Core (Low risk)
1. Gộp `configs/``core/config/`
2. Gộp `shared/` + `utils/``core/utils/`
3. Gộp `deferred/` + `directional/``core/navigation/`
4. Đổi `resources/``core/theme/`
### Phase 2: Reorganize Network & Services (Medium risk)
1. Di chuyển `networking/``core/network/`
2. Di chuyển `services/``core/services/`
3. Di chuyển `preference/``core/storage/`
### Phase 3: Feature-based organization (High risk, cần test kỹ)
1. Tạo structure cho từng feature
2. Di chuyển screens theo feature
3. Tạo data/domain/presentation layers
## Lợi ích
1. **Scalability**: Dễ thêm features mới
2. **Maintainability**: Code được tổ chức rõ ràng
3. **Testability**: Dễ test từng layer riêng biệt
4. **Team collaboration**: Nhiều người có thể làm việc trên các features khác nhau
5. **Code reuse**: Core layer có thể reuse cho nhiều features
## Lưu ý
- Migration cần làm từng bước, test kỹ sau mỗi bước
- Có thể giữ cấu trúc cũ song song trong thời gian transition
- Update imports và dependencies sau mỗi bước di chuyển
{
"flavor":"pro",
"baseUrl":"https://api.mypoint.com.vn/8854/gup2start/rest",
"t3Token":"runner-env-flavor-pro",
"t3Token":"runner-env-t3Token-pro",
"enableLogging":false
}
assets/icons/dev/app_icon.png

525 KB | W: | H:

assets/icons/dev/app_icon.png

108 KB | W: | H:

assets/icons/dev/app_icon.png
assets/icons/dev/app_icon.png
assets/icons/dev/app_icon.png
assets/icons/dev/app_icon.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/dev/ic_foreground.png

326 KB | W: | H:

assets/icons/dev/ic_foreground.png

86.1 KB | W: | H:

assets/icons/dev/ic_foreground.png
assets/icons/dev/ic_foreground.png
assets/icons/dev/ic_foreground.png
assets/icons/dev/ic_foreground.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/dev/ic_monochrome.png

6.96 KB | W: | H:

assets/icons/dev/ic_monochrome.png

828 Bytes | W: | H:

assets/icons/dev/ic_monochrome.png
assets/icons/dev/ic_monochrome.png
assets/icons/dev/ic_monochrome.png
assets/icons/dev/ic_monochrome.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/pro/app_icon.png

572 KB | W: | H:

assets/icons/pro/app_icon.png

110 KB | W: | H:

assets/icons/pro/app_icon.png
assets/icons/pro/app_icon.png
assets/icons/pro/app_icon.png
assets/icons/pro/app_icon.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/pro/ic_foreground.png

319 KB | W: | H:

assets/icons/pro/ic_foreground.png

83.9 KB | W: | H:

assets/icons/pro/ic_foreground.png
assets/icons/pro/ic_foreground.png
assets/icons/pro/ic_foreground.png
assets/icons/pro/ic_foreground.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/pro/ic_monochrome.png

6.96 KB | W: | H:

assets/icons/pro/ic_monochrome.png

828 Bytes | W: | H:

assets/icons/pro/ic_monochrome.png
assets/icons/pro/ic_monochrome.png
assets/icons/pro/ic_monochrome.png
assets/icons/pro/ic_monochrome.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/stg/app_icon.png

529 KB | W: | H:

assets/icons/stg/app_icon.png

110 KB | W: | H:

assets/icons/stg/app_icon.png
assets/icons/stg/app_icon.png
assets/icons/stg/app_icon.png
assets/icons/stg/app_icon.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/stg/ic_foreground.png

329 KB | W: | H:

assets/icons/stg/ic_foreground.png

89.9 KB | W: | H:

assets/icons/stg/ic_foreground.png
assets/icons/stg/ic_foreground.png
assets/icons/stg/ic_foreground.png
assets/icons/stg/ic_foreground.png
  • 2-up
  • Swipe
  • Onion skin
assets/icons/stg/ic_monochrome.png

6.96 KB | W: | H:

assets/icons/stg/ic_monochrome.png

828 Bytes | W: | H:

assets/icons/stg/ic_monochrome.png
assets/icons/stg/ic_monochrome.png
assets/icons/stg/ic_monochrome.png
assets/icons/stg/ic_monochrome.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -266,7 +266,7 @@ else:
if 'window.flutterConfiguration.renderer' not in content:
content = re.sub(
r'(window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};)',
r'\1\n window.flutterConfiguration.renderer = \'html\';',
r"\1\n window.flutterConfiguration.renderer = 'html';",
content
)
# Remove canvasKitBaseUrl and useLocalCanvasKit if they exist (not needed for HTML renderer)
......
......@@ -114,7 +114,7 @@ if 'window.flutterConfiguration.renderer' not in content:
# Add renderer config before flutter_bootstrap.js loads
content = re.sub(
r'(window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};)',
r'\1\n window.flutterConfiguration.renderer = \'html\';',
r"\1\n window.flutterConfiguration.renderer = 'html';",
content
)
......
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/dio_http_service.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart';
import 'package:mypoint_flutter_app/preference/point/point_manager.dart';
import 'package:mypoint_flutter_app/screen/home/header_home_viewmodel.dart';
import 'package:mypoint_flutter_app/base/app_loading.dart';
import 'package:mypoint_flutter_app/env_loader.dart';
import 'package:mypoint_flutter_app/web/web_helper.dart';
import '../firebase/push_setup.dart';
import 'package:mypoint_flutter_app/core/network/dio_http_service.dart';
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import 'package:mypoint_flutter_app/shared/widgets/loading/app_loading.dart';
import 'package:mypoint_flutter_app/app/config/env_loader.dart';
import 'package:mypoint_flutter_app/core/services/web/web_helper.dart';
import '../features/home/header_home_viewmodel.dart';
import '../core/firebase/push_notification.dart';
import '../core/firebase/push_setup.dart';
import '../core/services/deep_link_service.dart';
/// Main app initialization and setup
class AppInitializer {
/// Initialize all core app features
static Future<void> initialize() async {
debugPrint('🚀 Initializing app...');
// Load environment configuration
await loadEnv();
// Initialize data preferences
await DataPreference.instance.init();
// Initialize HTTP service
DioHttpService();
// Initialize GetX controllers
Get.put(HeaderThemeController(), permanent: true);
// Initialize Firebase (mobile only)
// await _initializeFirebase();
// Fetch user point if logged in
// await _fetchUserPointIfLoggedIn();
// Initialize web-specific features (including x-app-sdk)
await _initializeFirebase();
await _initializeWebFeatures();
// Initialize deep link handlers (Branch, URI schemes)
// await DeepLinkService().initialize();
await DeepLinkService().initialize();
debugPrint('✅ App initialization completed');
}
......@@ -39,7 +32,6 @@ class AppInitializer {
if (kIsWeb) {
debugPrint('🌐 Initializing web-specific features...');
try {
// Initialize x-app-sdk
await webInitializeXAppSDK();
await _configureWebSdkHeader();
debugPrint('✅ Web features initialized successfully');
......@@ -53,22 +45,8 @@ class AppInitializer {
/// Initialize Firebase and FCM (mobile only)
static Future<void> _initializeFirebase() async {
if (!kIsWeb) {
debugPrint('📱 Initializing Firebase for mobile...');
if (kIsWeb) return;
await initFirebaseAndFcm();
} else {
debugPrint('🌐 Skipping Firebase initialization for web');
}
}
/// Fetch user point if already logged in
static Future<void> _fetchUserPointIfLoggedIn() async {
if (DataPreference.instance.logged) {
debugPrint('💰 Fetching user point...');
await UserPointManager().fetchUserPoint();
} else {
debugPrint('👤 User not logged in, skipping point fetch');
}
}
static Future<void> _configureWebSdkHeader() async {
......@@ -98,10 +76,8 @@ class AppInitializer {
WidgetsBinding.instance.addPostFrameCallback((_) {
AppLoading().attach();
});
// Handle launch from notification when app was killed
// _handleInitialNotificationLaunch();
// Handle launch from local notification tap when app was killed
// handleLocalNotificationLaunchIfAny();
_handleInitialNotificationLaunch();
handleLocalNotificationLaunchIfAny();
} catch (e) {
debugPrint('Error in setupPostInitCallbacks: $e');
}
......@@ -110,17 +86,12 @@ class AppInitializer {
/// Handle initial notification launch (mobile only)
static Future<void> _handleInitialNotificationLaunch() async {
if (kIsWeb) return; // Skip for web
try {
// FirebaseMessaging is only available on mobile
// This code will not be included in web builds due to conditional imports
// final initial = await FirebaseMessaging.instance.getInitialMessage();
// debugPrint('Checking initial message for app launch from terminated state...$initial');
// if (initial == null) return;
// WidgetsBinding.instance.addPostFrameCallback((_) {
// Future.delayed(const Duration(seconds: 1), () {
// NotificationRouter.handleRemoteMessage(initial);
// });
// });
} catch (_) {}
final initial = await FirebaseMessaging.instance.getInitialMessage();
if (initial == null) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(const Duration(seconds: 1), () {
NotificationRouter.handleRemoteMessage(initial);
});
});
}
}
......@@ -39,6 +39,7 @@ class APIPaths {//sandbox
static const String submitGameCard = "/campaign/api/v3.0/games/%@/%@/submit";
static const String affiliateCategoryGetList = "/affiliateCategoryGetList/1.0.0";
static const String affiliateBrandGetList = "/affiliateBrandGetList/1.0.0";
static const String adsBannerByContextRequest = "/adsBannerByContextRequest/1.0.0";
static const String affiliateProductTopSale = "/affiliateProductTopSale/1.0.0";
static const String getCashbackOverview = "/cashback/overview";
static const String getCashbackStatus = "/cashback/status";
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment