first commit

This commit is contained in:
2025-03-03 20:59:42 +03:00
commit 273e68557a
1099 changed files with 17880 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
// Dart imports:
import 'dart:async';
// Flutter imports:
import 'package:flutter/material.dart';
///
/// Компонент для выполнения отложенных операций
///
class Debouncer {
///
/// Компонент для выполнения отложенных операций
///
/// Пример использования
///
/// ```dart
/// final Debouncer _searchDelayer = Debouncer(
/// delay: const Duration(milliseconds: 300),
/// );
///
/// Widget _buildButton(BuildContext) {
/// return ElevatedButton(
/// onPressed: () {
/// _debouncer.run(() {
/// debugPrint('Type your code here');
/// });
/// },
/// );
/// }
/// ```
///
Debouncer({
required this.delay,
});
/// Время через которое необходимо вызывать функцию
final Duration delay;
/// Таймер
Timer? _timer;
///
/// Запуск отложенного события
///
void run(VoidCallback action) {
_timer?.cancel();
_timer = Timer(delay, action);
}
}

30
lib/components/env.dart Normal file
View File

@@ -0,0 +1,30 @@
// Package imports:
import 'package:get_it/get_it.dart';
part 'env/dev_env.dart';
part 'env/prod_env.dart';
///
/// Базовый класс ENV
///
abstract class Env {
///
/// Указание на URL бекенда
///
Uri get url;
///
/// Режим работы приложения
///
String get mode;
///
/// Получение ENV более удобным для написания кода способом
///
static Env get get => Env.of();
///
/// Получение ENV
///
static Env of() => GetIt.I.get<Env>();
}

12
lib/components/env/dev_env.dart vendored Normal file
View File

@@ -0,0 +1,12 @@
part of '../env.dart';
///
/// DEV сборка
///
class DevEnv extends Env {
@override
Uri get url => Uri.parse('https://api.remever.dizoft-studio.ru');
@override
String get mode => 'dev';
}

12
lib/components/env/prod_env.dart vendored Normal file
View File

@@ -0,0 +1,12 @@
part of '../env.dart';
///
/// Продакшн сборка
///
class ProdEnv extends Env {
@override
Uri get url => Uri.parse('https://api.remever.dizoft-studio.ru');
@override
String get mode => 'prod';
}

View File

@@ -0,0 +1,21 @@
// Flutter imports:
import 'package:flutter/widgets.dart';
/// Подключение сторонней библиотеки
/// Сделано для упрощения чтения импортов
export 'package:flutter_screenutil/flutter_screenutil.dart';
///
/// Маштабирование в зависимости от контекста
///
extension ScaleFromContext on BuildContext {
///
/// Screen Width
///
double get sw => MediaQuery.of(this).size.width;
///
/// Screen Height
///
double get sh => MediaQuery.of(this).size.height;
}

View File

@@ -0,0 +1,21 @@
///
/// Расширение для работы с [Duration]
///
extension AppDuration on Duration {
///
/// Получение длительности в формате mm:ss
///
String get mmss => hhmmss.substring('00:'.length);
///
/// Получение длительности в формате HH:mm:ss
///
String get hhmmss {
String twoDigits(int n) => n.toString().padLeft(2, '0');
String twoDigitMinutes = twoDigits(inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(inSeconds.remainder(60));
return '${twoDigits(inHours)}:$twoDigitMinutes:$twoDigitSeconds';
}
}

View File

@@ -0,0 +1,26 @@
// Dart imports:
import 'dart:async';
// Flutter imports:
import 'package:flutter/material.dart';
extension StateExtension on State {
/// [setState] when it's not building, then wait until next frame built.
FutureOr<void> safeSetState(FutureOr<dynamic> Function() fn) async {
await fn();
if (mounted &&
!context.debugDoingBuild &&
context.owner?.debugBuilding == false) {
// ignore: invalid_use_of_protected_member, no-empty-block
setState(() {});
}
final Completer<void> completer = Completer<void>();
WidgetsBinding.instance.addPostFrameCallback((_) {
completer.complete();
});
return completer.future;
}
}

View File

@@ -0,0 +1,31 @@
// Flutter imports:
import 'package:flutter/material.dart' show Color;
///
/// Расширение для работы со строками
///
extension MString on String {
///
/// Слово с заглавной буквы
///
String capitalyze() {
final String str = toLowerCase();
final String first = str.substring(0, 1);
return '${first.toUpperCase()}${str.substring(1)}';
}
///
/// Парсинг hex string в color
///
Color get toColor {
String res = replaceFirst('#', '');
return Color(
int.parse(
res.length == 8 ? res : (res.length == 6 ? 'FF$res' : res),
radix: 16,
),
);
}
}

View File

@@ -0,0 +1,21 @@
// Flutter imports:
import 'package:flutter/material.dart' show ThemeMode;
/// Расширение [ThemeMode]
extension ThemModeExtension on ThemeMode {
///
/// Получение инверсивного [ThemeMode]
///
ThemeMode get inversed {
switch (this) {
case ThemeMode.system:
return ThemeMode.light;
case ThemeMode.light:
return ThemeMode.dark;
case ThemeMode.dark:
return ThemeMode.light;
}
}
}

View File

@@ -0,0 +1,38 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:get_it/get_it.dart';
import 'package:hive_ce_flutter/hive_flutter.dart';
import 'package:remever/common/storage.dart';
import 'package:remever/services/core/theme_service.dart';
// Project imports:
/// Описание функции для построения содержимого [ThemeModeListener]
typedef ThemeModeBuilder =
Widget Function(BuildContext context, ThemeMode themeMode);
class ThemeModeListener extends StatelessWidget {
///
/// Слушатель изменений темы
///
const ThemeModeListener({required this.builder, super.key});
/// Построитель
final ThemeModeBuilder builder;
@override
Widget build(BuildContext context) {
final ThemeService service = GetIt.I.get<ThemeService>();
return ValueListenableBuilder<Box<ThemeMode>>(
valueListenable: hiveTheme.listenable(),
builder: (BuildContext context, _, Widget? child) {
if (child != null) return child;
return builder(context, service.themeMode);
},
);
}
}

View File

@@ -0,0 +1,39 @@
// Flutter imports:
import 'package:flutter/material.dart' show ChangeNotifier;
///
/// Динамические параметры для конфигурирования приложения
///
class AppSettingsNotifier extends ChangeNotifier {
///
/// Динамические параметры для конфигурирования приложения
///
AppSettingsNotifier({
this.debugMode = false,
this.showFps = false,
});
/// Включение дебаг мода
bool debugMode;
/// Отображение FPS
bool showFps;
///
/// Переключение режима "Дебаг"
///
void toggleDebugMode() {
debugMode = !debugMode;
notifyListeners();
}
///
/// Переключение режима "Дебаг"
///
void toggleFps() {
showFps = !showFps;
notifyListeners();
}
}

View File

@@ -0,0 +1,18 @@
// Flutter imports:
import 'package:flutter/foundation.dart';
class CollectionData extends ChangeNotifier {
CollectionData({this.showFAB = true});
/// Флаг показа
bool showFAB;
/// Смена состояния показа Fab на экране коллекции
void showFab(bool show) {
if (showFAB != show) {
showFAB = show;
notifyListeners();
}
}
}