7 Commits

Author SHA1 Message Date
zl0y4951
550a1de182 feat(app): добавил сгенерированный файл 2025-06-19 11:17:44 +03:00
zl0y4951
7291a5e514 chore(.gitignore): убрал игнорирование кодогена 2025-06-19 11:17:27 +03:00
zl0y4951
2129e16b85 refactor(app, debug): заменил использование расширение контекста 2025-06-18 15:24:20 +03:00
zl0y4951
a4d61d4453 feat(app): добавил theme_tailor кодогенерацию темы 2025-06-18 15:23:42 +03:00
zl0y4951
9179344358 chore(pubspec): добавил theme_tailor в зависимости 2025-06-18 15:22:56 +03:00
zl0y4951
f97632e0cd chore(.gitignore): добавил игнорирование кодогенерации 2025-06-18 15:21:40 +03:00
Artem Luzin
4d746ce23c feat(theme): Добавить ThemeExtension для токенов цвета (#12)
* feat
* fix
* fix: исправил ширину строки
* feat: добавить визуальный элемент
2025-06-18 14:54:32 +03:00
9 changed files with 227 additions and 44 deletions

View File

@@ -10,9 +10,6 @@ extension AppContextExt on BuildContext {
/// Метод для получения экземпляра DIContainer
DiContainer get di => read<DiContainer>();
/// Геттер для получения цветовой схемы
ColorScheme get colors => Theme.of(this).colorScheme;
/// Геттер для получения темы
ThemeNotifier get theme => read<ThemeNotifier>();

View File

@@ -1,18 +1,65 @@
import 'package:flutter/material.dart';
import 'package:theme_tailor_annotation/theme_tailor_annotation.dart';
part 'app_colors_scheme.tailor.dart';
/// {@template app_colors}
/// Класс, реализующий расширение для добавления токенов в цветовую схему
extension AppColorsScheme on ColorScheme {
bool get _isDark => brightness == Brightness.dark;
/// {@endtemplate}
@TailorMixin(themeGetter: ThemeGetter.onBuildContext)
class AppColors extends ThemeExtension<AppColors> with _$AppColorsTailorMixin {
/// {@macro app_colors}
///
/// Принимает:
///
/// * [testColor] - цвет тестового текста
/// * [errorSnackbarBackground] - цвет фона снекбара ошибки
/// * [successSnackbarBackground] - цвет фона снекбара успеха
/// * [infoSnackbarBackground] - цвет фона снекбара информации
/// * [itemTextColor] - цвет элемента текста
const AppColors({
required this.testColor,
required this.itemTextColor,
required this.errorSnackbarBackground,
required this.successSnackbarBackground,
required this.infoSnackbarBackground,
});
// Тестовый цвет
Color get testColor => _isDark ? Colors.green : Colors.red;
/// Цвет тестовый
@override
final Color testColor;
/// Цвет заднего фона снекбара с ошибкой
Color get errorSnackbarBackground => const Color(0xFFD24720);
/// Цвет элемента текста
@override
final Color itemTextColor;
/// Цвет заднего фона снекбара с успехом
Color get successSnackbarBackground => const Color(0xFF6FB62C);
/// Цвет фона снекбара ошибки
@override
final Color errorSnackbarBackground;
/// Цвет заднего фона снекбара с информацией
Color get infoSnackbarBackground => const Color.fromARGB(255, 220, 108, 77);
/// Цвет фона снекбара успеха
@override
final Color successSnackbarBackground;
/// Цвет фона снекбара информации
@override
final Color infoSnackbarBackground;
/// Цвета светлой темы
static final AppColors light = AppColors(
testColor: Colors.red,
errorSnackbarBackground: const Color(0xFFD24720),
successSnackbarBackground: const Color(0xFF6FB62C),
infoSnackbarBackground: const Color.fromARGB(255, 220, 108, 77),
itemTextColor: const Color(0xFFFAF3EB),
);
/// Цвета тёмной темы
static final AppColors dark = AppColors(
testColor: Colors.green,
errorSnackbarBackground: const Color(0xFF638B8B),
successSnackbarBackground: const Color(0xFF93C499),
infoSnackbarBackground: const Color.fromARGB(255, 35, 147, 178),
itemTextColor: Colors.white,
);
}

View File

@@ -0,0 +1,102 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'app_colors_scheme.dart';
// **************************************************************************
// TailorAnnotationsGenerator
// **************************************************************************
mixin _$AppColorsTailorMixin on ThemeExtension<AppColors> {
Color get testColor;
Color get itemTextColor;
Color get errorSnackbarBackground;
Color get successSnackbarBackground;
Color get infoSnackbarBackground;
@override
AppColors copyWith({
Color? testColor,
Color? itemTextColor,
Color? errorSnackbarBackground,
Color? successSnackbarBackground,
Color? infoSnackbarBackground,
}) {
return AppColors(
testColor: testColor ?? this.testColor,
itemTextColor: itemTextColor ?? this.itemTextColor,
errorSnackbarBackground:
errorSnackbarBackground ?? this.errorSnackbarBackground,
successSnackbarBackground:
successSnackbarBackground ?? this.successSnackbarBackground,
infoSnackbarBackground:
infoSnackbarBackground ?? this.infoSnackbarBackground,
);
}
@override
AppColors lerp(covariant ThemeExtension<AppColors>? other, double t) {
if (other is! AppColors) return this as AppColors;
return AppColors(
testColor: Color.lerp(testColor, other.testColor, t)!,
itemTextColor: Color.lerp(itemTextColor, other.itemTextColor, t)!,
errorSnackbarBackground: Color.lerp(
errorSnackbarBackground,
other.errorSnackbarBackground,
t,
)!,
successSnackbarBackground: Color.lerp(
successSnackbarBackground,
other.successSnackbarBackground,
t,
)!,
infoSnackbarBackground: Color.lerp(
infoSnackbarBackground,
other.infoSnackbarBackground,
t,
)!,
);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is AppColors &&
const DeepCollectionEquality().equals(testColor, other.testColor) &&
const DeepCollectionEquality().equals(
itemTextColor,
other.itemTextColor,
) &&
const DeepCollectionEquality().equals(
errorSnackbarBackground,
other.errorSnackbarBackground,
) &&
const DeepCollectionEquality().equals(
successSnackbarBackground,
other.successSnackbarBackground,
) &&
const DeepCollectionEquality().equals(
infoSnackbarBackground,
other.infoSnackbarBackground,
));
}
@override
int get hashCode {
return Object.hash(
runtimeType.hashCode,
const DeepCollectionEquality().hash(testColor),
const DeepCollectionEquality().hash(itemTextColor),
const DeepCollectionEquality().hash(errorSnackbarBackground),
const DeepCollectionEquality().hash(successSnackbarBackground),
const DeepCollectionEquality().hash(infoSnackbarBackground),
);
}
}
extension AppColorsBuildContext on BuildContext {
AppColors get appColors => Theme.of(this).extension<AppColors>()!;
}

View File

@@ -1,10 +1,15 @@
import 'package:flutter/material.dart';
import 'package:friflex_starter/app/theme/app_colors_scheme.dart';
/// Класс для конфигурации светлой/темной темы приложения
abstract class AppTheme {
/// Геттер для получения светлой темы
static ThemeData get light => ThemeData.light();
static ThemeData get light => ThemeData.light().copyWith(
extensions: <ThemeExtension<Object?>>[AppColors.light],
);
/// Геттер для получения темной темы
static ThemeData get dark => ThemeData.dark();
static ThemeData get dark => ThemeData.dark().copyWith(
extensions: <ThemeExtension<Object?>>[AppColors.dark],
);
}

View File

@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:friflex_starter/app/app_context_ext.dart';
import 'package:friflex_starter/app/theme/app_colors_scheme.dart';
import 'package:friflex_starter/app/ui_kit/app_box.dart';
@@ -265,9 +264,9 @@ class _AppSnackBarState extends State<AppSnackBar>
/// [TypeSnackBar.error] - цвет ошибки
Color _getBackgroundColor(TypeSnackBar type) {
return switch (type) {
TypeSnackBar.success => context.colors.successSnackbarBackground,
TypeSnackBar.error => context.colors.errorSnackbarBackground,
TypeSnackBar.info => context.colors.infoSnackbarBackground,
TypeSnackBar.success => context.appColors.successSnackbarBackground,
TypeSnackBar.error => context.appColors.errorSnackbarBackground,
TypeSnackBar.info => context.appColors.infoSnackbarBackground,
};
}
}

View File

@@ -37,7 +37,7 @@ class LangScreen extends StatelessWidget {
Text(
'Тестовое слово bold: ${context.l10n.helloWorld}',
style: TextStyle(
color: context.colors.testColor,
color: context.appColors.testColor,
fontFamily: Assets.fonts.montserratBold,
),
),
@@ -45,7 +45,7 @@ class LangScreen extends StatelessWidget {
Text(
'Тестовое слово medium: ${context.l10n.helloWorld}',
style: TextStyle(
color: context.colors.testColor,
color: context.appColors.testColor,
fontFamily: FontFamily.montserrat,
),
),

View File

@@ -11,6 +11,7 @@ class ThemeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colors = context.appColors;
return Scaffold(
appBar: AppBar(title: const Text('Theme')),
body: Center(
@@ -25,11 +26,29 @@ class ThemeScreen extends StatelessWidget {
),
const SizedBox(height: 16),
ColoredBox(
color: context.colors.testColor,
color: context.appColors.testColor,
child: const SizedBox(height: 100, width: 100),
),
const SizedBox(height: 16),
Text('Текущая тема: ${context.theme.themeMode}'),
Card(
elevation: 4,
shadowColor: colors.infoSnackbarBackground,
margin: const EdgeInsets.symmetric(vertical: 10),
color: colors.infoSnackbarBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: ListTile(
title: Text(
'Текущая тема: ${context.theme.themeMode}',
style: TextStyle(
color: colors.itemTextColor,
fontWeight: FontWeight.bold,
),
),
trailing: Icon(Icons.color_lens, color: colors.itemTextColor),
),
),
],
),
),

View File

@@ -5,23 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
sha256: e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f
url: "https://pub.dev"
source: hosted
version: "76.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.3"
version: "82.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
sha256: "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0"
url: "https://pub.dev"
source: hosted
version: "6.11.0"
version: "7.4.5"
ansicolor:
dependency: transitive
description:
@@ -225,10 +220,10 @@ packages:
dependency: transitive
description:
name: dart_style
sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820"
sha256: "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af"
url: "https://pub.dev"
source: hosted
version: "2.3.8"
version: "3.1.0"
dartx:
dependency: transitive
description:
@@ -592,14 +587,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.1"
macros:
dependency: transitive
description:
name: macros
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.3-main.0"
matcher:
dependency: transitive
description:
@@ -881,10 +868,18 @@ packages:
dependency: transitive
description:
name: source_gen
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
version: "2.0.0"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c"
url: "https://pub.dev"
source: hosted
version: "1.3.5"
source_span:
dependency: transitive
description:
@@ -989,6 +984,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.4"
theme_tailor:
dependency: "direct dev"
description:
name: theme_tailor
sha256: ba98be1d04856deef932757a3ca8fa7a5e2a6f96c30466a59c48924eeb608b97
url: "https://pub.dev"
source: hosted
version: "3.0.3"
theme_tailor_annotation:
dependency: "direct main"
description:
name: theme_tailor_annotation
sha256: "0d5ecd13a6a52add2082aa60497179f6093acf482eb69e7fa3a9f37eb990ac34"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
time:
dependency: transitive
description:

View File

@@ -32,6 +32,8 @@ dependencies:
equatable: 2.0.7
theme_tailor_annotation: 3.0.2
### основной сервис с интерфейсами
i_app_services:
path: ./app_services/i_app_services
@@ -50,6 +52,7 @@ dev_dependencies:
flutter_gen_runner: 5.10.0
flutter_gen: 5.10.0
flutter_lints: 6.0.0
theme_tailor: 3.0.3
flutter:
uses-material-design: true