- 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
14 KiB
🎨 Кнопки Bottom Sheet - Расположение и Иконки
📍 Где находятся эти кнопки?
Файл: lib/features/profile/add/add_profile_modal.dart
Класс: AddProfileModal (extends HookConsumerWidget)
🖼️ Структура кнопок
1. "Добавить из буфера обмена" (Clipboard)
_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)
_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"
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. "Ввести вручную"
_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:
dependencies:
fluentui_system_icons: ^1.1.229
Импорт:
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
Icon(
FluentIcons.clipboard_paste_24_regular,
size: buttonWidth / 3,
color: theme.colorScheme.primary, // ← ЦВЕТ ИЗ ТЕМЫ
)
Откуда берётся цвет:
theme.colorScheme.primary- основной цвет темы- Меняется автоматически при смене темы (светлая/тёмная)
- Определяется в настройках темы приложения
🎨 Где определяется тема?
Путь к настройкам темы:
// Тема определяется в:
lib/core/preferences/
lib/features/config_option/
Как работает смена цвета:
- Пользователь выбирает тему (светлую/тёмную/автоматическую)
- Flutter Theme система применяет
ColorScheme - ColorScheme.primary меняется на цвет из палитры темы
- Icon виджеты автоматически перерисовываются с новым цветом
Пример:
// Светлая тема
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: Использовать другую иконку из того же пакета
// Было:
icon: FluentIcons.clipboard_paste_24_regular,
// Стало:
icon: FluentIcons.copy_24_regular, // Другая иконка
Посмотреть все доступные иконки: https://github.com/microsoft/fluentui-system-icons/tree/main/fonts
Вариант 2: Использовать Material Icons
// Изменить импорт
import 'package:flutter/material.dart';
// Использовать Material иконку
icon: Icons.content_paste,
Вариант 3: Использовать свои SVG иконки
1. Добавьте пакет flutter_svg:
dependencies:
flutter_svg: ^2.0.10
2. Сохраните SVG в assets:
assets/images/icons/clipboard.svg
assets/images/icons/qr_code.svg
3. Используйте в коде:
// Вместо Icon виджета
SvgPicture.asset(
'assets/images/icons/clipboard.svg',
width: size / 3,
height: size / 3,
colorFilter: ColorFilter.mode(
theme.colorScheme.primary,
BlendMode.srcIn,
),
)
🔧 Как изменить размер иконок?
Icon(
FluentIcons.clipboard_paste_24_regular,
size: buttonWidth / 3, // ← РАЗМЕР
color: theme.colorScheme.primary,
)
Текущий размер: buttonWidth / 3
- buttonWidth рассчитывается из ширины экрана
- Примерно 48-56 пикселей для иконки
Чтобы изменить:
// Фиксированный размер
size: 64,
// Относительный размер
size: buttonWidth / 2, // Больше
size: buttonWidth / 4, // Меньше
🎨 Как изменить цвет иконок?
Вариант 1: Использовать другой цвет из темы
Icon(
FluentIcons.clipboard_paste_24_regular,
color: theme.colorScheme.secondary, // Вторичный цвет
// или:
// color: theme.colorScheme.tertiary,
// color: theme.colorScheme.error,
// color: theme.colorScheme.onSurface,
)
Вариант 2: Использовать кастомный цвет
Icon(
FluentIcons.clipboard_paste_24_regular,
color: Color(0xFF00FF00), // Зелёный
// или:
// color: Colors.red,
// color: Colors.amber,
)
Вариант 3: Градиент (сложнее)
Для градиента нужно использовать ShaderMask:
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):
if (!PlatformUtils.isDesktop)
_Button(
label: t.profile.add.scanQr,
icon: FluentIcons.qr_code_24_regular,
)
Показывается:
- ✅ Добавить из буфера обмена
- ✅ Сканировать QR-код
- ✅ Добавить WARP
- ✅ Ввести вручную
Desktop (Windows/macOS/Linux):
else
_Button(
label: t.profile.add.manually,
icon: FluentIcons.add_24_regular,
)
Показывается:
- ✅ Добавить из буфера обмена
- ✅ Ввести вручную (вместо QR)
- ✅ Добавить WARP
🎯 Класс _Button
Виджет для квадратных кнопок:
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 цвет:
// Вероятно в:
lib/core/preferences/general_preferences_provider.dart
lib/core/theme/
Umbrix использует:
- Primary color: Бирюзовый/голубой (#00BCD4 или похожий)
- Surface: Фон карточек
- OnSurface: Текст на фоне
💡 Быстрые изменения
Изменить цвет всех иконок на красный:
Icon(
icon,
size: size / 3,
color: Colors.red, // ← ВСЕ ИКОНКИ СТАНУТ КРАСНЫМИ
)
Изменить размер иконок на больший:
Icon(
icon,
size: size / 2, // ← БЫЛО /3, СТАЛО /2 (больше)
color: color,
)
Использовать заполненные (filled) иконки:
// Было:
icon: FluentIcons.clipboard_paste_24_regular,
// Стало:
icon: FluentIcons.clipboard_paste_24_filled, // Заполненная версия
🔍 Где ещё используются FluentIcons?
Поиск по проекту:
grep -r "FluentIcons\." lib/ | wc -l
# Результат: Много! Используются по всему приложению
Примеры файлов:
lib/features/home/widget/home_page.dartlib/features/proxy/overview/proxies_overview_page.dartlib/features/common/adaptive_root_scaffold.dart
📚 Полезные ссылки
-
Fluent UI Icons Gallery: https://aka.ms/fluentui-system-icons
-
Flutter Icon класс: https://api.flutter.dev/flutter/widgets/Icon-class.html
-
ColorScheme документация: https://api.flutter.dev/flutter/material/ColorScheme-class.html
-
Пакет 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берётся из настроек темы- Светлая/тёмная тема → разные оттенки
Чтобы изменить:
- Цвет → поменять
color: theme.colorScheme.primaryна другой - Размер → изменить
size: buttonWidth / 3 - Иконку → заменить
FluentIcons.clipboard_paste_24_regularна другую - Свою иконку → использовать SVG через flutter_svg пакет