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,16 @@
///
///
///
abstract interface class AuthInterface {
/// Проверка авторизации
Future<bool> get isAuth;
/// Получение токена
Future<String?> get token;
/// Авторизация
Future<String?> login(String email);
/// Отправка кода
Future<bool> sendCode(String code, String uid);
}

View File

@@ -0,0 +1,72 @@
import 'package:dio/dio.dart';
import 'package:dio_smart_retry/dio_smart_retry.dart';
import 'package:injectable/injectable.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/common/services/api_client.dart';
import 'package:remever/common/storage.dart';
import 'package:remever/common/typedef.dart';
import 'package:remever/services/auth_interface.dart';
///
/// Сервис авторизации
///
@Singleton(as: AuthInterface)
final class AuthService implements AuthInterface {
@override
Future<bool> get isAuth async => await token != null;
@override
Future<String?> get token async {
final String? accessToken = await authSecStorage.read(
key: StorageKeys.accessToken,
);
return accessToken;
}
@override
Future<String?> login(String email) async {
try {
final Response<dynamic> result = await apiClient.post(
'/auth/email/send',
options: Options()..disableRetry = true,
data: <String, dynamic>{'email': email.toLowerCase()},
);
final Json response = Json.from(result.data);
if (response['success'] == false) return null;
return response['result']['authUid'];
} catch (e) {
return null;
}
}
@override
Future<bool> sendCode(String code, String uid) async {
try {
final Response<dynamic> result = await apiClient.post(
'/auth/code/login',
options: Options()..disableRetry = true,
data: <String, dynamic>{'authUid': uid, 'confirmCode': code},
);
final Json response = Json.from(result.data);
final bool success = response['success'] ?? false;
if (success) {
await authSecStorage.write(
key: StorageKeys.accessToken,
value: response['result']['token'],
);
}
return success;
} catch (e) {
return false;
}
}
}

View File

@@ -0,0 +1,4 @@
///
/// Базовый сервис для сервисов, которые не будут меняться от проекта к проекту
///
abstract class CoreService {}

View File

@@ -0,0 +1,52 @@
// Dart imports:
import 'dart:convert';
import 'dart:typed_data';
import 'package:hive_ce/hive.dart';
import 'package:remever/common/storage.dart';
import 'core_service.dart';
///
/// Сервис для работы с ключами шифрования
///
class EncKeysService extends CoreService {
///
/// Получение ключа для шифрования
///
Future<String> getRawKey(String keyFor) async {
String? encKey = await hiveKeysStorage.read(key: keyFor);
if (encKey == null) {
final List<int> hiveKey = Hive.generateSecureKey();
encKey = base64UrlEncode(hiveKey);
await hiveKeysStorage.write(key: keyFor, value: encKey);
}
return encKey;
}
///
/// Получение ключа шифрования
///
/// Если ключа ранее не существовало - он будет создан
///
Future<Uint8List> getKey(String keyFor) async {
String? encKey = await getRawKey(keyFor);
return base64Url.decode(encKey);
}
///
/// Получение ключа шифрования в виде строки
///
/// Если ключа ранее не существовало - он будет создан
///
Future<String> getStringKey(String keyFor) async {
final Uint8List key = await getKey(keyFor);
return String.fromCharCodes(key);
}
}

View File

@@ -0,0 +1,42 @@
import 'package:remever/common/resources.dart';
import 'package:remever/common/storage.dart';
import 'package:remever/i18n/strings.g.dart';
import 'package:remever/interfaces/warmup_service.dart';
import 'core_service.dart';
///
/// Сервис для работы с языками приложения
///
class LangService extends CoreService implements IWarmupService {
///
/// Установка языка при первом запуске
///
@override
Future<void> init() async {
final AppLocale deviceLocale = await LocaleSettings.useDeviceLocale();
AppLocale? locale = hiveLang.get(StorageKeys.langCode);
if (locale == null) {
LocaleSettings.setLocale(deviceLocale);
hiveLang.put(StorageKeys.langCode, deviceLocale);
} else {
LocaleSettings.setLocale(locale);
}
}
///
/// Получение текущей локали
///
AppLocale get locale =>
hiveLang.get(StorageKeys.langCode, defaultValue: AppLocale.en)!;
///
/// Запись и установка языка
///
Future<void> setLanguage(AppLocale locale) async {
await hiveLang.put(StorageKeys.langCode, locale);
LocaleSettings.setLocale(locale);
}
}

View File

@@ -0,0 +1,48 @@
// Flutter imports:
import 'package:flutter/material.dart' show ThemeMode;
import 'package:remever/common/resources.dart';
import 'package:remever/common/storage.dart';
import 'package:remever/components/extensions/theme_mode.dart';
import 'package:remever/interfaces/warmup_service.dart';
import 'core_service.dart';
///
/// Сервис для работы с темой приложения
///
class ThemeService extends CoreService implements IWarmupService {
@override
Future<void> init() async {
final ThemeMode? theme = hiveTheme.get(StorageKeys.themeKey);
if (theme == null) {
await hiveTheme.put(StorageKeys.themeKey, ThemeMode.light);
}
}
///
/// Получение текущего значения для темы
///
/// По-умолчанию - светлый
///
ThemeMode get themeMode {
return hiveTheme.get(StorageKeys.themeKey, defaultValue: ThemeMode.light)!;
}
///
/// Обновление темы приложения
///
/// [oldThemeMode] должно быть текущее значение темы. Автоматически будет
/// вызван метод {inversed}
///
Future<void> update(ThemeMode oldThemeMode) async {
return updateInversed(oldThemeMode.inversed);
}
///
/// Обновление темы приложения
///
Future<void> updateInversed(ThemeMode themeMode) async {
return hiveTheme.put(StorageKeys.themeKey, themeMode);
}
}

View File

@@ -0,0 +1,106 @@
// Dart imports:
import 'dart:async';
// Flutter imports:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hive_ce/hive.dart';
import 'package:injectable/injectable.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/components/notifiers/app_settings.dart';
import 'package:remever/components/notifiers/home_screen_data.dart';
import 'package:remever/helpers/hive_creator.dart';
import 'package:remever/i18n/strings.g.dart';
import 'package:remever/interfaces/warmup_service.dart';
import 'package:remever/models/adapters/app_locale_adapter.dart';
import 'package:remever/models/adapters/theme_mode_adapter.dart';
import '../inject.dart';
import 'core/enc_keys_service.dart';
import 'core/lang_service.dart';
import 'core/theme_service.dart';
///
/// Сервис прогрева приложения
///
@Singleton()
class WarmupService {
WarmupService(this._themeService, this._langService, this._encKeysService);
/// Сервисы
final ThemeService _themeService;
final LangService _langService;
final EncKeysService _encKeysService;
/// [Completer] для прогрева приложения
final Completer<bool> _firstStartCompleter = Completer<bool>();
Completer<bool> get firstStartCompleter => _firstStartCompleter;
@PostConstruct(preResolve: true)
Future<void> common() async {
await _registerHiveAdapters();
await _openHiveBoxes();
await _registerNotifiers();
}
///
/// Инициализация для запуска приложения
///
Future<void> firstStart() async {
await _setStoragesValue();
}
///
/// Проставнока изначальных значений хранилищ
///
Future<void> _setStoragesValue() async {
final List<IWarmupService> services = <IWarmupService>[
_themeService,
_langService,
];
for (final IWarmupService service in services) {
await service.init();
}
}
///
/// Регистрация [Hive] адаптеров
///
Future<void> _registerHiveAdapters() async {
Hive.registerAdapter<ThemeMode>(ThemeModeAdapter());
Hive.registerAdapter<AppLocale>(AppLocaleAdapter());
}
///
/// Открытие [Hive] хранилищ
///
Future<void> _openHiveBoxes() async {
final Map<String, HiveCreator<dynamic>> storageNames =
<String, HiveCreator<dynamic>>{
Storage.storageAuth: HiveCreator<String>(),
Storage.hiveThemeMode: HiveCreator<ThemeMode>(),
Storage.hiveLang: HiveCreator<AppLocale>(),
};
for (MapEntry<String, HiveCreator<dynamic>> storage
in storageNames.entries) {
final String name = storage.key;
final Uint8List key = await _encKeysService.getKey(name);
await storage.value.open(name, HiveAesCipher(key));
}
}
///
/// Регистрация нотификаторов
///
Future<void> _registerNotifiers() async {
getIt.registerLazySingleton<AppSettingsNotifier>(
() => AppSettingsNotifier(debugMode: kDebugMode),
);
getIt.registerLazySingleton<CollectionData>(() => CollectionData());
}
}