forked from eatvio/eatvio_app
doc(readme): README.md update
This commit is contained in:
455
README.md
455
README.md
@@ -1,14 +1,449 @@
|
|||||||
# eatvio_app
|
# Eatvio - Nutrition & Diet Management Application
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
---
|
Eatvio is a comprehensive mobile application connecting users with nutrition consultants, providing diet planning tools, recipes, food diary tracking, and professional consultation services. The application is specifically designed for Russian-speaking users interested in nutrition and healthy eating.
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
- **Blog Posts**: Educational nutrition content and articles
|
||||||
|
- **Nutrition Consultation**: Professional consultation services with certified nutritionists
|
||||||
|
- **Recipes**: User-generated and professional recipes with nutritional information
|
||||||
|
- **Diets**: Structured diet plans with daily schedules
|
||||||
|
- **Nutrition Plans**: Long-term nutrition planning and tracking
|
||||||
|
|
||||||
|
### Target Audience
|
||||||
|
- **Primary**: Russian-speaking users interested in nutrition and healthy eating
|
||||||
|
- **Secondary**: Certified nutrition consultants offering professional services
|
||||||
|
- **Market**: Russian Federation and Russian-speaking countries
|
||||||
|
|
||||||
|
### Business Model
|
||||||
|
- Paid consultations with nutritionists
|
||||||
|
- Content marketplace for premium diets and plans
|
||||||
|
- Subscription-based features for consultants
|
||||||
|
|
||||||
|
### Platform Information
|
||||||
|
- **Mobile**: iOS and Android (including Huawei devices)
|
||||||
|
- **Language**: Russian (ru)
|
||||||
|
- **Current Version**: 1.3.0+79 (build 79)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### Flutter & Dart Versions
|
||||||
|
- **Flutter**: SDK 3.8.0+
|
||||||
|
- **Dart**: Language version >=3.8.0 <4.0.0
|
||||||
|
|
||||||
|
### Platform-Specific Requirements
|
||||||
|
|
||||||
|
#### Android
|
||||||
|
- **NDK Version**: 27.0.12077973
|
||||||
|
- **Huawei HMS Dependencies**:
|
||||||
|
- Huawei Push (6.12.0.300)
|
||||||
|
- Huawei Analytics (6.12.0.300)
|
||||||
|
- **Google Play Services**
|
||||||
|
- **ProGuard** for code obfuscation
|
||||||
|
- **Compile SDK**: Flutter default
|
||||||
|
- **Min SDK**: Flutter default
|
||||||
|
- **Target SDK**: Flutter default
|
||||||
|
|
||||||
|
#### iOS
|
||||||
|
- **APNs** for push notifications
|
||||||
|
- **Deep linking** configuration
|
||||||
|
- **Xcode** version compatible with Flutter requirements
|
||||||
|
|
||||||
|
#### General IDE Requirements
|
||||||
|
- **VS Code** with Flutter/Dart extensions
|
||||||
|
- **Android Studio** with Flutter plugin
|
||||||
|
- **Visual Studio Code** recommended for development
|
||||||
|
|
||||||
|
## Environment Configuration
|
||||||
|
|
||||||
|
### .env Setup Process
|
||||||
|
|
||||||
|
1. Copy the environment template:
|
||||||
|
```bash
|
||||||
|
cp env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Edit the `.env` file with your configuration values
|
||||||
|
|
||||||
|
### Required Environment Variables
|
||||||
|
|
||||||
|
#### API URLs
|
||||||
|
- `BASE_URL` - основной URL API (по умолчанию: https://eatvio.ru)
|
||||||
|
- `DEV_BASE_URL` - URL API для разработки (по умолчанию: https://dev2.eatvio.com)
|
||||||
|
|
||||||
|
#### Sentry Configuration
|
||||||
|
- `SENTRY_DSN` - DSN для Sentry мониторинга
|
||||||
|
|
||||||
|
#### Firebase Configuration
|
||||||
|
- `FIREBASE_PROJECT_ID` - ID проекта Firebase
|
||||||
|
- `FIREBASE_DATABASE_URL` - URL базы данных Firebase
|
||||||
|
- `FIREBASE_STORAGE_BUCKET` - bucket для хранения файлов
|
||||||
|
- `FIREBASE_MESSAGING_SENDER_ID` - ID отправителя сообщений
|
||||||
|
|
||||||
|
#### Firebase Android Configuration
|
||||||
|
- `FIREBASE_ANDROID_API_KEY` - API ключ для Android
|
||||||
|
- `FIREBASE_ANDROID_APP_ID` - ID приложения для Android
|
||||||
|
|
||||||
|
#### Firebase iOS Configuration
|
||||||
|
- `FIREBASE_IOS_API_KEY` - API ключ для iOS
|
||||||
|
- `FIREBASE_IOS_APP_ID` - ID приложения для iOS
|
||||||
|
- `FIREBASE_IOS_BUNDLE_ID` - Bundle ID для iOS
|
||||||
|
|
||||||
|
#### App Store URLs
|
||||||
|
- `APP_STORE_URL` - URL App Store
|
||||||
|
- `RUSTORE_URL` - URL RuStore
|
||||||
|
|
||||||
|
#### Support URLs
|
||||||
|
- `TELEGRAM_SUPPORT_URL` - URL поддержки в Telegram
|
||||||
|
- `SUPPORT_EMAIL` - email для поддержки
|
||||||
|
|
||||||
|
#### Test Credentials (только для разработки)
|
||||||
|
- `TEST_EMAIL` - тестовый email
|
||||||
|
- `TEST_PASSWORD` - тестовый пароль
|
||||||
|
|
||||||
|
#### Email Validation API
|
||||||
|
- `EMAIL_VALIDATION_API_URL` - URL API для валидации email
|
||||||
|
|
||||||
|
#### Connection Check URLs
|
||||||
|
- `GOOGLE_CHECK_URL` - URL для проверки соединения (Google)
|
||||||
|
- `YANDEX_CHECK_URL` - URL для проверки соединения (Yandex)
|
||||||
|
|
||||||
|
#### VK ID Configuration
|
||||||
|
- `VK_CLIENT_ID` - ID приложения VK (числовой)
|
||||||
|
- **Примечание**: VK_CLIENT_ID - это числовой "ID приложения" из консоли VK ID, НЕ "Защищённый ключ" или "Сервисный ключ доступа"
|
||||||
|
|
||||||
|
#### Yandex ID Configuration
|
||||||
|
- `YANDEX_CLIENT_ID` - ID приложения Yandex OAuth
|
||||||
|
- `YANDEX_CLIENT_SECRET` - секретный ключ приложения Yandex OAuth
|
||||||
|
- `YANDEX_REDIRECT_URI` - URI для перенаправления (должен совпадать с настройками в Yandex OAuth приложении)
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
### Core Framework
|
||||||
|
- **Flutter**: SDK 3.8.0+
|
||||||
|
- **Dart**: Language version >=3.8.0 <4.0.0
|
||||||
|
- **Version**: 1.3.0+79 (build 79)
|
||||||
|
|
||||||
|
### State Management
|
||||||
|
- **flutter_bloc**: ^9.1.1 - BLoC pattern implementation
|
||||||
|
- **equatable**: ^2.0.7 - Value equality for state objects
|
||||||
|
|
||||||
|
### Data Management
|
||||||
|
- **freezed**: ^3.2.0 - Immutable data classes
|
||||||
|
- **freezed_annotation**: ^3.1.0 - Code generation annotations
|
||||||
|
- **json_annotation**: ^4.9.0 - JSON serialization
|
||||||
|
- **json_serializable**: ^6.10.0 - JSON code generation
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
- **dio**: ^5.9.0 - HTTP client
|
||||||
|
- **retrofit**: ^4.7.1 - Type-safe REST client
|
||||||
|
- **retrofit_generator**: ^10.0.2 - Retrofit code generation
|
||||||
|
- **http**: ^1.5.0 - Additional HTTP support
|
||||||
|
- **http_parser**: ^4.1.2 - HTTP parsing utilities
|
||||||
|
|
||||||
|
### Real-time Communication
|
||||||
|
- **dart_pusher_channels**: ^1.2.3 - WebSocket support via Pusher
|
||||||
|
- **connectivity_plus**: ^6.1.5 - Network connectivity monitoring
|
||||||
|
|
||||||
|
### Navigation & Routing
|
||||||
|
- **go_router**: ^16.1.0 - Declarative routing
|
||||||
|
- Deep linking support for content
|
||||||
|
|
||||||
|
### UI Components
|
||||||
|
- **cached_network_image**: ^3.4.1 - Image caching
|
||||||
|
- **flutter_svg**: ^2.2.0 - SVG rendering
|
||||||
|
- **google_fonts**: ^6.3.0 - Mulish font family
|
||||||
|
- **carousel_slider_plus**: ^7.1.1 - Carousel widgets
|
||||||
|
- **photo_view**: ^0.15.0 - Image viewer
|
||||||
|
- **dismissible_page**: ^1.0.2 - Swipe to dismiss
|
||||||
|
- **badges**: ^3.1.2 - Notification badges
|
||||||
|
- **lottie**: ^3.3.1 - Animation support
|
||||||
|
- **flutter_portal**: ^1.1.4 - Overlay widgets
|
||||||
|
- **dotted_border**: ^3.1.0 - Dotted borders
|
||||||
|
- **flutter_rating_bar**: ^4.0.1 - Rating widgets
|
||||||
|
|
||||||
|
### Forms & Input
|
||||||
|
- **flutter_form_builder**: ^10.2.0 - Form management
|
||||||
|
- **validators**: ^3.0.0 - Input validation
|
||||||
|
- **flutter_typeahead**: ^5.2.0 - Autocomplete
|
||||||
|
- **keyboard_dismisser**: ^3.0.0 - Keyboard management
|
||||||
|
- **flutter_keyboard_visibility**: ^6.0.0 - Keyboard state
|
||||||
|
- **mask_text_input_formatter**: ^2.9.0 - Input masking
|
||||||
|
|
||||||
|
### Media & Files
|
||||||
|
- **image_picker**: ^1.2.0 - Image selection
|
||||||
|
- **flutter_image_compress**: ^2.4.0 - Image compression
|
||||||
|
- **image**: ^4.5.4 - Image manipulation
|
||||||
|
- **file_picker**: ^10.3.1 - File selection
|
||||||
|
- **audioplayers**: ^6.5.0 - Audio playback
|
||||||
|
- **qr_code_scanner_plus**: ^2.0.10+1 - QR code scanning
|
||||||
|
|
||||||
|
### Data Visualization
|
||||||
|
- **syncfusion_flutter_charts**: ^30.2.5 - Chart widgets
|
||||||
|
- **syncfusion_flutter_gauges**: ^30.2.5 - Gauge widgets
|
||||||
|
- **table_calendar**: ^3.2.0 - Calendar widget
|
||||||
|
|
||||||
|
### Storage & Persistence
|
||||||
|
- **shared_preferences**: ^2.5.3 - Local key-value storage
|
||||||
|
- **path_provider**: ^2.1.5 - File system paths
|
||||||
|
- **path**: ^1.9.1 - Path manipulation
|
||||||
|
|
||||||
|
### Firebase
|
||||||
|
- **firebase_core**: ^4.0.0 - Firebase initialization
|
||||||
|
- **firebase_messaging**: ^16.0.0 - Push notifications
|
||||||
|
|
||||||
|
### Analytics & Monitoring
|
||||||
|
- **sentry_flutter**: ^9.6.0 - Error tracking
|
||||||
|
- **appmetrica_plugin**: ^3.3.0 - Analytics (Russian market)
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- **vk_id**: ^1.0.3 - VK social login
|
||||||
|
- **flutter_login_yandex**: ^0.0.5 - Yandex ID login
|
||||||
|
- OAuth support for OK and Mail.ru
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
- **url_launcher**: ^6.3.2 - URL handling
|
||||||
|
- **easy_debounce**: ^2.0.3 - Debouncing
|
||||||
|
- **share_plus**: ^11.1.0 - Content sharing
|
||||||
|
- **flutter_html**: ^3.0.0 - HTML rendering
|
||||||
|
- **webview_flutter**: ^4.13.0 - WebView
|
||||||
|
- **intl**: ^0.20.2 - Internationalization
|
||||||
|
- **collection**: ^1.19.1 - Collection utilities
|
||||||
|
- **uuid**: ^4.5.1 - UUID generation
|
||||||
|
- **visibility_detector**: ^0.4.0+2 - Visibility tracking
|
||||||
|
- **fluttertoast**: ^8.2.12 - Toast messages
|
||||||
|
- **version**: ^3.0.2 - Version management
|
||||||
|
- **package_info_plus**: ^8.3.1 - Package info
|
||||||
|
- **device_info_plus**: ^11.5.0 - Device information
|
||||||
|
- **permission_handler**: ^12.0.1 - Permissions
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Code Generation
|
||||||
|
- Run `flutter pub run build_runner build` for code generation
|
||||||
|
- Run `flutter pub run build_runner build --delete-conflicting-outputs` for clean generation
|
||||||
|
- Use `flutter pub run build_runner watch` for watch mode
|
||||||
|
|
||||||
|
### Environment Setup
|
||||||
|
- Configure `.env` file with all required variables
|
||||||
|
- Set up Firebase for both Android and iOS platforms
|
||||||
|
- Configure social authentication providers (VK, Yandex, etc.)
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- Unit tests with `flutter_test`
|
||||||
|
- Integration tests with `integration_test`
|
||||||
|
- Mocking with `mockito`
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
### Development Builds
|
||||||
```bash
|
```bash
|
||||||
# apt install linux-oem-24.04
|
# Run on connected device
|
||||||
# sudo apt-get install --install-recommends linux-lowlatency-hwe-24.04
|
flutter run
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
ubuntu switch to hwe [kernel](https://canonical-kernel-docs.readthedocs-hosted.com/latest/reference/hwe-kernels/#installing-a-hwe-kernel)
|
|
||||||
|
|
||||||
---
|
# Run on specific Android device
|
||||||
ubuntu instal intel iRIS gpu [drivers](https://dgpu-docs.intel.com/driver/client/overview.html#ubuntu-latest)
|
flutter run -d emulator-5554
|
||||||
|
|
||||||
|
# Run on specific iOS simulator
|
||||||
|
flutter run -d iPhone\ 15
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Builds
|
||||||
|
|
||||||
|
#### Android
|
||||||
|
```bash
|
||||||
|
# Build APK (split by ABI)
|
||||||
|
flutter build apk --release --split-per-abi
|
||||||
|
|
||||||
|
# Build App Bundle
|
||||||
|
flutter build appbundle --release
|
||||||
|
|
||||||
|
# Huawei-specific build (with HMS)
|
||||||
|
flutter build apk --release --flavor production --target-platform android-arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
#### iOS
|
||||||
|
```bash
|
||||||
|
# Build IPA for TestFlight
|
||||||
|
flutter build ipa --export-options-plist=ExportOptions.plist
|
||||||
|
|
||||||
|
# Build for specific device architecture
|
||||||
|
flutter build ipa --export-options-plist=ExportOptions.plist --no-codesign
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optimization Techniques
|
||||||
|
|
||||||
|
### Android Build Optimization
|
||||||
|
1. **ProGuard Rules**:
|
||||||
|
- Configure rules in [`android/app/proguard-rules.pro`](android/app/proguard-rules.pro:1)
|
||||||
|
- Essential rules for Flutter:
|
||||||
|
```
|
||||||
|
-keep class io.flutter.app.** { *; }
|
||||||
|
-keep class io.flutter.plugin.** { *; }
|
||||||
|
-keep class io.flutter.util.** { *; }
|
||||||
|
-keep class io.flutter.view.** { *; }
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Resource Shrinking**:
|
||||||
|
- Enabled in `android/app/build.gradle`:
|
||||||
|
```gradle
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
shrinkResources true
|
||||||
|
minifyEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Code Obfuscation**:
|
||||||
|
- Use `--obfuscate` flag with build commands
|
||||||
|
- Verify with `flutter build apk --release --obfuscate --split-debug-info=debug-info/`
|
||||||
|
|
||||||
|
4. **Image Compression Workflow**:
|
||||||
|
- Automatic compression via [`flutter_image_compress`](lib/features/create_diet/models/create_diet_model.dart:1)
|
||||||
|
- Configuration in image upload flows:
|
||||||
|
```dart
|
||||||
|
final compressedFile = await FlutterImageCompress.compressWithFile(
|
||||||
|
file.path,
|
||||||
|
quality: 85,
|
||||||
|
minWidth: 1024,
|
||||||
|
minHeight: 1024,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### Missing .env Variables
|
||||||
|
- **Symptom**: Application crashes on startup with "Missing environment variable" error
|
||||||
|
- **Solution**:
|
||||||
|
1. Verify `.env` file exists in project root
|
||||||
|
2. Check [`ENV_SETUP.md`](ENV_SETUP.md) for required variables
|
||||||
|
3. Regenerate configuration with `flutter clean && flutter pub get`
|
||||||
|
|
||||||
|
#### Firebase Configuration Errors
|
||||||
|
- **Android**:
|
||||||
|
- Missing `google-services.json` in `android/app/`
|
||||||
|
- Missing `agconnect-services.json` for Huawei devices
|
||||||
|
- Verify SHA-1 fingerprints match Firebase console
|
||||||
|
- **iOS**:
|
||||||
|
- Missing `GoogleService-Info.plist` in `ios/Runner`
|
||||||
|
- Check bundle identifier matches Firebase project
|
||||||
|
|
||||||
|
#### WebSocket Connection Failures
|
||||||
|
- **Symptoms**: Chat messages not delivering, real-time updates not working
|
||||||
|
- **Solutions**:
|
||||||
|
1. Verify Pusher configuration in [`lib/core/websockets/ws_manager.dart`](lib/core/websockets/ws_manager.dart:1)
|
||||||
|
2. Check network connectivity with `connectivity_plus` package
|
||||||
|
3. Ensure proper authentication token is sent with WebSocket connection
|
||||||
|
|
||||||
|
#### Platform-Specific Build Errors
|
||||||
|
- **Huawei vs Google Services**:
|
||||||
|
- For Huawei devices, ensure `agconnect-services.json` is present
|
||||||
|
- Use `--flavor` flag to specify build variant:
|
||||||
|
```bash
|
||||||
|
flutter build apk --release --flavor hms
|
||||||
|
```
|
||||||
|
- Check for conflicting dependencies between HMS and GMS
|
||||||
|
|
||||||
|
- **iOS Code Signing Issues**:
|
||||||
|
- Verify `ExportOptions.plist` contains correct provisioning profiles
|
||||||
|
- Update signing certificates in Xcode
|
||||||
|
- Clean build folder: `flutter clean && rm -rf ios/Pods ios/Podfile.lock`
|
||||||
|
|
||||||
|
## Key Implementation Details
|
||||||
|
|
||||||
|
### Content View Tracking
|
||||||
|
- `ViewsCubit` handles visibility detection
|
||||||
|
- `VisibilityDetector` widget tracks on-screen time
|
||||||
|
- Views sent to backend when 50%+ visible for 2+ seconds
|
||||||
|
- Debounced to prevent excessive API calls
|
||||||
|
|
||||||
|
### Image Handling
|
||||||
|
- `ImagePicker` for selection
|
||||||
|
- `FlutterImageCompress` for compression
|
||||||
|
- MultiPart form data upload via Dio
|
||||||
|
- Preview via `CachedNetworkImage`
|
||||||
|
|
||||||
|
### Search Implementation
|
||||||
|
- Debounced search with 500ms delay
|
||||||
|
- Min query length: 3 characters
|
||||||
|
- Applied to: Feed, Recipes, Diets, Plans, Consultants
|
||||||
|
- Tag-based filtering for recipes
|
||||||
|
|
||||||
|
### Pagination Pattern
|
||||||
|
- Page-based pagination
|
||||||
|
- Scroll detection for next page load
|
||||||
|
- Loading state during fetch
|
||||||
|
- Meta data tracking (current page, last page)
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- Bearer token authentication
|
||||||
|
- Secure token storage
|
||||||
|
- Automatic session management
|
||||||
|
- OAuth 2.0 for social login
|
||||||
|
|
||||||
|
### Data Protection
|
||||||
|
- HTTPS only communication
|
||||||
|
- Token encryption in storage
|
||||||
|
- Secure WebSocket connections
|
||||||
|
- Privacy policy compliance
|
||||||
|
|
||||||
|
## Key Files Reference
|
||||||
|
|
||||||
|
### Entry Point
|
||||||
|
- `lib/main.dart` - App initialization
|
||||||
|
|
||||||
|
### Core Infrastructure
|
||||||
|
- `lib/core/app_initializer.dart` - Startup sequence
|
||||||
|
- `lib/core/locator_service.dart` - DI container
|
||||||
|
- `lib/core/app_config.dart` - App configuration
|
||||||
|
- `lib/core/app_router.dart` - Routing setup
|
||||||
|
|
||||||
|
### WebSocket
|
||||||
|
- `lib/core/websockets/ws_manager.dart` - Connection management
|
||||||
|
- `lib/core/websockets/ws_service.dart` - API service
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- `lib/features/auth/sdk/social_auth_facade.dart` - Social auth
|
||||||
|
- `lib/core/token_storage.dart` - Token persistence
|
||||||
|
- `lib/core/interceptors/token_interceptor.dart` - Auth interceptor
|
||||||
|
|
||||||
|
### Environment
|
||||||
|
- `lib/core/env_config.dart` - Environment variables
|
||||||
|
- `.env` - Environment file (not in repo)
|
||||||
|
|
||||||
|
## Key Success Metrics
|
||||||
|
|
||||||
|
- User engagement with food diary
|
||||||
|
- Consultation bookings and completion rates
|
||||||
|
- Content creation by consultants
|
||||||
|
- User retention and progress tracking
|
||||||
|
|
||||||
|
## Documentation Standards
|
||||||
|
|
||||||
|
- **Last Updated**: 2025-10-16
|
||||||
|
- All paths are relative to `/home/apoloz/dev/eatvio_app`
|
||||||
|
- Russian market focus maintained throughout documentation
|
||||||
|
- Version compatibility matrix:
|
||||||
|
| Component | Version | Notes |
|
||||||
|
|-----------|---------|-------|
|
||||||
|
| Flutter | 3.8.0+ | Required |
|
||||||
|
| Dart | 3.8.0-3.9.9 | Required |
|
||||||
|
| Android SDK | 34 | Target SDK |
|
||||||
|
| iOS Deployment | 14.0 | Minimum |
|
||||||
|
|
||||||
|
## Ubuntu Development PC Optimization
|
||||||
|
```bash
|
||||||
|
-# apt install linux-oem-24.04
|
||||||
|
-# sudo apt-get install --install-recommends linux-lowlatency-hwe-24.04
|
||||||
|
```
|
||||||
|
----
|
||||||
|
- ubuntu switch to hwe [kernel](https://canonical-kernel-docs.readthedocs-hosted.com/latest/reference/hwe-kernels/#installing-a-hwe-kernel)
|
||||||
|
----
|
||||||
|
- ubuntu instal intel iRIS gpu [drivers](https://dgpu-docs.intel.com/driver/client/overview.html#ubuntu-latest)
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user