forked from eatvio/eatvio_app
- Новый SbpQrBottomSheet: рендер checkout_url (qr.nspk.ru/{qrcId}) через qr_flutter,
сумма, инструкция, автоопределение оплаты polling-ом статуса chosen_plan (3 сек)
и автозакрытие с успехом
- Кнопка «Оплатить по QR-коду» в шите выбора банков — первичная, под заголовком,
доступна сразу после получения checkout_url, не дожидаясь списка банков
(важно для устройств без банковских приложений, iOS в РФ)
- Блок «Симуляция оплаты» (testpay.alfabank.ru/sbp-page?qrcId=...) показывается
только когда base URL API не продуктовый: AppConfig.isProdApi/prodApiHosts
(хост целиком — стенды-поддомены eatvio.ru продом не считаются)
- showBottomSheetWithBlur стал генериком — возвращает значение pop(result)
- showConsultationPaymentFlow: опциональная прокидка суммы в QR-шит
- Локализация ru/en, тесты (16 новых, всего 34 платёжных зелёные)
112 lines
4.5 KiB
Dart
112 lines
4.5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:eatvio_app/core/app_initializer.dart';
|
|
import 'package:eatvio_app/core/cubit/marketing/marketing_cubit.dart';
|
|
import 'package:eatvio_app/core/env_config.dart';
|
|
import 'package:eatvio_app/core/internet_connection_cubit/internet_connection_cubit.dart';
|
|
import 'package:eatvio_app/core/locator_service.dart';
|
|
import 'package:eatvio_app/core/prefs.dart';
|
|
import 'package:eatvio_app/core/prefs_keys.dart';
|
|
import 'package:eatvio_app/core/views/cubit/views_cubit.dart';
|
|
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
|
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
|
|
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
|
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
|
import 'package:eatvio_app/features/video_calls/presentation/bloc/video_call_session/video_call_session_cubit.dart';
|
|
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
|
import 'package:eatvio_app/generated/l10n.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
|
|
/// Конфигурация приложения
|
|
class AppConfig {
|
|
AppConfig({required this.buildType}) {
|
|
_baseUrl = switch (buildType) {
|
|
AppBuildType.prod => EnvConfig.baseUrl,
|
|
AppBuildType.tests => EnvConfig.devBaseUrl,
|
|
AppBuildType.dev => EnvConfig.devBaseUrl,
|
|
};
|
|
}
|
|
|
|
final AppBuildType buildType;
|
|
late String _baseUrl;
|
|
String get baseUrl => _baseUrl;
|
|
|
|
/// Продуктовые хосты API. Сравнение по хосту целиком: поддомены
|
|
/// (например `*-hasan.eatvio.ru`) — это стенды разработки, не прод.
|
|
static const List<String> prodApiHosts = ['eatvio.ru', 'eatvio.com'];
|
|
|
|
/// Текущий base URL указывает на продуктовый API?
|
|
bool get isProdApi {
|
|
final host = Uri.tryParse(baseUrl)?.host.toLowerCase() ?? '';
|
|
if (host.isEmpty) return false;
|
|
return prodApiHosts.any((prodHost) => host == prodHost || host == 'www.$prodHost');
|
|
}
|
|
|
|
/// Работаем на стенде разработки/stage (не на продуктовом API)?
|
|
bool get isDevOrStageStand => !isProdApi;
|
|
|
|
void setBaseUrl(String baseUrls) {
|
|
_baseUrl = baseUrls;
|
|
_persistBaseUrl(baseUrls);
|
|
}
|
|
|
|
void _persistBaseUrl(String baseUrl) {
|
|
if (!sl.isRegistered<Prefs>()) {
|
|
return;
|
|
}
|
|
final normalized = baseUrl.trim();
|
|
if (normalized.isEmpty) {
|
|
unawaited(sl<Prefs>().remove(PrefsKeys.customBaseUrl));
|
|
return;
|
|
}
|
|
unawaited(sl<Prefs>().setString(PrefsKeys.customBaseUrl, normalized));
|
|
unawaited(sl<Prefs>().setString(PrefsKeys.apiBaseUrl, normalized));
|
|
}
|
|
|
|
/// Список глобальных BlocProvider'ов
|
|
/// Используются lazy: true для отложенной инициализации, чтобы не блокировать старт приложения
|
|
List<BlocProvider> get globalBlocProviders => [
|
|
BlocProvider<VideoCallSessionCubit>.value(
|
|
value: sl<VideoCallSessionCubit>(),
|
|
),
|
|
BlocProvider<NewMessagesCubit>(
|
|
lazy: true,
|
|
create: (context) => sl<NewMessagesCubit>(),
|
|
),
|
|
BlocProvider<NotificationsCubit>(
|
|
lazy: true,
|
|
create: (context) => sl<NotificationsCubit>(),
|
|
),
|
|
BlocProvider<FeedCubit>(lazy: true, create: (context) => sl<FeedCubit>()),
|
|
BlocProvider<ProfileAvatarCubit>(
|
|
lazy: true,
|
|
create: (context) => sl<ProfileAvatarCubit>(),
|
|
),
|
|
BlocProvider<ChatsCubit>(lazy: true, create: (context) => sl<ChatsCubit>()),
|
|
BlocProvider<ViewsCubit>(lazy: true, create: (context) => sl<ViewsCubit>()),
|
|
BlocProvider<InternetConnectionCubit>(
|
|
lazy: false,
|
|
create: (context) => sl<InternetConnectionCubit>(),
|
|
),
|
|
BlocProvider<MarketingCubit>(
|
|
lazy: true,
|
|
create: (context) => sl<MarketingCubit>(),
|
|
),
|
|
];
|
|
|
|
/// Делегаты локализации
|
|
List<LocalizationsDelegate> get localizationDelegates => [
|
|
S.delegate,
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
];
|
|
|
|
/// Поддерживаемые локали
|
|
List<Locale> get supportedLocales => [
|
|
const Locale.fromSubtags(languageCode: 'ru'),
|
|
];
|
|
}
|