Files
umbrix/docs/BOTTOM_SHEET_BUTTONS.md
Umbrix Developer 76a374950f feat: mobile-like window size and always-visible stats
- Changed window size to mobile phone format (400x800)
- Removed width condition for ActiveProxyFooter - now always visible
- Added run-umbrix.sh launch script with icon copying
- Stats cards now display on all screen sizes
2026-01-17 13:09:20 +03:00

524 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎨 Кнопки Bottom Sheet - Расположение и Иконки
## 📍 Где находятся эти кнопки?
**Файл:** [lib/features/profile/add/add_profile_modal.dart](../lib/features/profile/add/add_profile_modal.dart)
**Класс:** `AddProfileModal` (extends `HookConsumerWidget`)
---
## 🖼️ Структура кнопок
### 1. **"Добавить из буфера обмена"** (Clipboard)
```dart
_Button(
key: const ValueKey("add_from_clipboard_button"),
label: t.profile.add.fromClipboard,
icon: FluentIcons.clipboard_paste_24_regular, // ← ИКОНКА
size: buttonWidth,
onTap: () async {
final captureResult = await Clipboard.getData(Clipboard.kTextPlain).then((value) => value?.text ?? '');
if (addProfileState.isLoading) return;
ref.read(addProfileProvider.notifier).add(captureResult);
},
)
```
**Иконка:** `FluentIcons.clipboard_paste_24_regular`
**Перевод:** `t.profile.add.fromClipboard` → "Добавить из буфера обмена"
**Цвет:** `theme.colorScheme.primary` (основной цвет темы)
---
### 2. **"Сканировать QR-код"** (QR Code)
```dart
_Button(
key: const ValueKey("add_by_qr_code_button"),
label: t.profile.add.scanQr,
icon: FluentIcons.qr_code_24_regular, // ← ИКОНКА
size: buttonWidth,
onTap: () async {
final cr = await const QRCodeScannerScreen().open(context);
if (cr == null) return;
if (addProfileState.isLoading) return;
ref.read(addProfileProvider.notifier).add(cr);
},
)
```
**Иконка:** `FluentIcons.qr_code_24_regular`
**Перевод:** `t.profile.add.scanQr` → "Сканировать QR-код"
**Цвет:** `theme.colorScheme.primary`
**Условие:** Показывается только на мобильных (`!PlatformUtils.isDesktop`)
---
### 3. **"Добавить WARP"**
```dart
Material(
key: const ValueKey("add_warp_button"),
elevation: 8,
color: theme.colorScheme.surface,
surfaceTintColor: theme.colorScheme.surfaceTint,
shadowColor: Colors.transparent,
borderRadius: BorderRadius.circular(8),
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () async {
await addProfileModal(context, ref);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
FluentIcons.add_24_regular, // ← ИКОНКА
color: theme.colorScheme.primary,
),
const SizedBox(width: 8),
Text(
t.profile.add.addWarp, // "Добавить WARP"
style: theme.textTheme.labelLarge?.copyWith(
color: theme.colorScheme.primary,
),
),
],
),
),
)
```
**Иконка:** `FluentIcons.add_24_regular`
**Перевод:** `t.profile.add.addWarp` → "Добавить WARP"
**Стиль:** Полная ширина кнопка с текстом и иконкой
---
### 4. **"Ввести вручную"**
```dart
_Button(
key: const ValueKey("add_manually_button"),
label: t.profile.add.manually,
icon: FluentIcons.add_24_regular, // ← ИКОНКА
size: buttonWidth,
onTap: () async {
context.pop();
await const NewProfileRoute().push(context);
},
)
```
**Иконка:** `FluentIcons.add_24_regular`
**Перевод:** `t.profile.add.manually` → "Ввести вручную"
**Условие:**
- На мобильных → показывается как отдельная кнопка внизу
- На Desktop → показывается вместо кнопки "Сканировать QR-код"
---
## 🎨 Откуда берутся иконки?
### Пакет: **fluentui_system_icons**
**pubspec.yaml:**
```yaml
dependencies:
fluentui_system_icons: ^1.1.229
```
**Импорт:**
```dart
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
```
### Используемые иконки:
| Иконка | Код | Описание |
|--------|-----|----------|
| 📋 | `FluentIcons.clipboard_paste_24_regular` | Буфер обмена |
| 📷 | `FluentIcons.qr_code_24_regular` | QR-код |
| | `FluentIcons.add_24_regular` | Добавить/Плюс |
---
## 🎨 Как иконки меняют цвет?
### Автоматическая смена цвета через Theme
```dart
Icon(
FluentIcons.clipboard_paste_24_regular,
size: buttonWidth / 3,
color: theme.colorScheme.primary, // ← ЦВЕТ ИЗ ТЕМЫ
)
```
**Откуда берётся цвет:**
- `theme.colorScheme.primary` - основной цвет темы
- Меняется автоматически при смене темы (светлая/тёмная)
- Определяется в настройках темы приложения
---
## 🎨 Где определяется тема?
**Путь к настройкам темы:**
```dart
// Тема определяется в:
lib/core/preferences/
lib/features/config_option/
```
**Как работает смена цвета:**
1. **Пользователь выбирает тему** (светлую/тёмную/автоматическую)
2. **Flutter Theme система** применяет `ColorScheme`
3. **ColorScheme.primary** меняется на цвет из палитры темы
4. **Icon виджеты** автоматически перерисовываются с новым цветом
**Пример:**
```dart
// Светлая тема
colorScheme: ColorScheme.light(
primary: Color(0xFF007AFF), // Синий
)
// Тёмная тема
colorScheme: ColorScheme.dark(
primary: Color(0xFF0A84FF), // Светло-синий
)
```
---
## 📦 Формат иконок
### FluentUI System Icons - это векторные иконки
**Технические детали:**
- **Формат:** IconData (Flutter встроенный формат)
- **Источник:** Microsoft Fluent Design System
- **Размер:** Масштабируемые (векторные, не растровые)
- **Цвет:** Одноцветные, цвет задаётся программно
- **Вариации:** `_regular`, `_filled` (обычные и заполненные)
**НЕ PNG, НЕ SVG файлы!** Это встроенные векторные глифы в шрифте.
---
## 🎨 Как изменить иконки?
### Вариант 1: Использовать другую иконку из того же пакета
```dart
// Было:
icon: FluentIcons.clipboard_paste_24_regular,
// Стало:
icon: FluentIcons.copy_24_regular, // Другая иконка
```
**Посмотреть все доступные иконки:**
https://github.com/microsoft/fluentui-system-icons/tree/main/fonts
### Вариант 2: Использовать Material Icons
```dart
// Изменить импорт
import 'package:flutter/material.dart';
// Использовать Material иконку
icon: Icons.content_paste,
```
### Вариант 3: Использовать свои SVG иконки
**1. Добавьте пакет flutter_svg:**
```yaml
dependencies:
flutter_svg: ^2.0.10
```
**2. Сохраните SVG в assets:**
```
assets/images/icons/clipboard.svg
assets/images/icons/qr_code.svg
```
**3. Используйте в коде:**
```dart
// Вместо Icon виджета
SvgPicture.asset(
'assets/images/icons/clipboard.svg',
width: size / 3,
height: size / 3,
colorFilter: ColorFilter.mode(
theme.colorScheme.primary,
BlendMode.srcIn,
),
)
```
---
## 🔧 Как изменить размер иконок?
```dart
Icon(
FluentIcons.clipboard_paste_24_regular,
size: buttonWidth / 3, // ← РАЗМЕР
color: theme.colorScheme.primary,
)
```
**Текущий размер:** `buttonWidth / 3`
- buttonWidth рассчитывается из ширины экрана
- Примерно 48-56 пикселей для иконки
**Чтобы изменить:**
```dart
// Фиксированный размер
size: 64,
// Относительный размер
size: buttonWidth / 2, // Больше
size: buttonWidth / 4, // Меньше
```
---
## 🎨 Как изменить цвет иконок?
### Вариант 1: Использовать другой цвет из темы
```dart
Icon(
FluentIcons.clipboard_paste_24_regular,
color: theme.colorScheme.secondary, // Вторичный цвет
// или:
// color: theme.colorScheme.tertiary,
// color: theme.colorScheme.error,
// color: theme.colorScheme.onSurface,
)
```
### Вариант 2: Использовать кастомный цвет
```dart
Icon(
FluentIcons.clipboard_paste_24_regular,
color: Color(0xFF00FF00), // Зелёный
// или:
// color: Colors.red,
// color: Colors.amber,
)
```
### Вариант 3: Градиент (сложнее)
Для градиента нужно использовать `ShaderMask`:
```dart
ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
colors: [Colors.blue, Colors.purple],
).createShader(bounds);
},
child: Icon(
FluentIcons.clipboard_paste_24_regular,
size: buttonWidth / 3,
color: Colors.white, // Базовый цвет (будет заменён градиентом)
),
)
```
---
## 📱 Адаптивность кнопок
### Мобильные (Android/iOS):
```dart
if (!PlatformUtils.isDesktop)
_Button(
label: t.profile.add.scanQr,
icon: FluentIcons.qr_code_24_regular,
)
```
**Показывается:**
- ✅ Добавить из буфера обмена
- ✅ Сканировать QR-код
- ✅ Добавить WARP
- ✅ Ввести вручную
### Desktop (Windows/macOS/Linux):
```dart
else
_Button(
label: t.profile.add.manually,
icon: FluentIcons.add_24_regular,
)
```
**Показывается:**
- ✅ Добавить из буфера обмена
- ✅ Ввести вручную (вместо QR)
- ✅ Добавить WARP
---
## 🎯 Класс _Button
**Виджет для квадратных кнопок:**
```dart
class _Button extends StatelessWidget {
final String label; // Текст кнопки
final IconData icon; // Иконка (FluentIcons.*)
final double size; // Размер кнопки (квадрат)
final VoidCallback onTap; // Действие при нажатии
@override
Widget build(BuildContext context) {
return SizedBox(
width: size,
height: size,
child: Material(
elevation: 8, // Тень
color: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(8),
child: InkWell(
onTap: onTap,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, size: size / 3, color: color),
const Gap(16),
Text(label, style: labelStyle),
],
),
),
),
);
}
}
```
**Свойства:**
- Квадратная форма (`width = height = size`)
- Иконка вверху (1/3 размера кнопки)
- Текст внизу
- Скругленные углы (8px)
- Тень (elevation: 8)
- Ripple эффект при нажатии (InkWell)
---
## 🎨 Цветовая схема по умолчанию
**Где определяется primary цвет:**
```dart
// Вероятно в:
lib/core/preferences/general_preferences_provider.dart
lib/core/theme/
```
**Umbrix использует:**
- **Primary color:** Бирюзовый/голубой (#00BCD4 или похожий)
- **Surface:** Фон карточек
- **OnSurface:** Текст на фоне
---
## 💡 Быстрые изменения
### Изменить цвет всех иконок на красный:
```dart
Icon(
icon,
size: size / 3,
color: Colors.red, // ← ВСЕ ИКОНКИ СТАНУТ КРАСНЫМИ
)
```
### Изменить размер иконок на больший:
```dart
Icon(
icon,
size: size / 2, // ← БЫЛО /3, СТАЛО /2 (больше)
color: color,
)
```
### Использовать заполненные (filled) иконки:
```dart
// Было:
icon: FluentIcons.clipboard_paste_24_regular,
// Стало:
icon: FluentIcons.clipboard_paste_24_filled, // Заполненная версия
```
---
## 🔍 Где ещё используются FluentIcons?
**Поиск по проекту:**
```bash
grep -r "FluentIcons\." lib/ | wc -l
# Результат: Много! Используются по всему приложению
```
**Примеры файлов:**
- `lib/features/home/widget/home_page.dart`
- `lib/features/proxy/overview/proxies_overview_page.dart`
- `lib/features/common/adaptive_root_scaffold.dart`
---
## 📚 Полезные ссылки
1. **Fluent UI Icons Gallery:**
https://aka.ms/fluentui-system-icons
2. **Flutter Icon класс:**
https://api.flutter.dev/flutter/widgets/Icon-class.html
3. **ColorScheme документация:**
https://api.flutter.dev/flutter/material/ColorScheme-class.html
4. **Пакет fluentui_system_icons:**
https://pub.dev/packages/fluentui_system_icons
---
## 🎯 Резюме
**Кнопки находятся:** `lib/features/profile/add/add_profile_modal.dart`
**Иконки:**
- Формат: IconData из пакета `fluentui_system_icons`
- НЕ файлы PNG/SVG, а векторные глифы в шрифте
- Цвет: `theme.colorScheme.primary` (меняется с темой)
- Размер: Масштабируемые, задаются программно
**Смена цвета:**
- Автоматическая через Theme системы Flutter
- `colorScheme.primary` берётся из настроек темы
- Светлая/тёмная тема → разные оттенки
**Чтобы изменить:**
1. Цвет → поменять `color: theme.colorScheme.primary` на другой
2. Размер → изменить `size: buttonWidth / 3`
3. Иконку → заменить `FluentIcons.clipboard_paste_24_regular` на другую
4. Свою иконку → использовать SVG через flutter_svg пакет