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

14 KiB
Raw Blame History

🎨 Кнопки 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/

Как работает смена цвета:

  1. Пользователь выбирает тему (светлую/тёмную/автоматическую)
  2. Flutter Theme система применяет ColorScheme
  3. ColorScheme.primary меняется на цвет из палитры темы
  4. 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.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 пакет