import 'dart:async'; import 'package:arasystem_app/app.dart'; import 'package:arasystem_app/core/api/dio_provider.dart'; import 'package:arasystem_app/core/api/user_agent.dart'; import 'package:arasystem_app/core/constants/app_info_provider.dart'; import 'package:arasystem_app/core/files/downloaded_files.dart'; import 'package:arasystem_app/core/files/picked_files.dart'; import 'package:arasystem_app/core/push/firebase_push_messaging.dart'; import 'package:arasystem_app/core/push/push_messaging.dart'; import 'package:arasystem_app/core/storage/first_run_marker.dart'; import 'package:arasystem_app/core/storage/secure_store.dart'; import 'package:arasystem_app/core/storage/token_store.dart'; import 'package:arasystem_app/core/storage/token_store_provider.dart'; import 'package:arasystem_app/core/theme/app_fonts.dart'; import 'package:arasystem_app/core/utils/provider_retry.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; /// `.env` 파일 이름 (pubspec assets) const String _envFileName = '.env'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); // .env 가 없으면 기본 주소로 동작한다 (ApiConfig.fromEnv) try { await dotenv.load(fileName: _envFileName); } on FileNotFoundError { // 기본값을 쓴다 } on EmptyEnvFileError { // 기본값을 쓴다 } AppFonts.registerFontLicenses(); // 토큰 보관 준비 — 첫 실행이면 보안 저장소에 남은 값을 지운다(앱을 띄우기 전에 끝낸다) final TokenStore tokenStore = TokenStore( secure: const FlutterSecureStore(), firstRun: PrefsFirstRunMarker(), ); await tokenStore.prepare(); final ({ String? appVersion, String? packageName, String userAgent, int? androidSdkInt, }) device = await loadAppDeviceInfo(); // 새 메일 알림(FCM) — Firebase 를 띄우고 플러그인의 소식 줄(FID · 받은 알림 · 누른 알림)을 지금 듣는다. // 띄우지 못하면(google-services.json 없이 빌드 · 5초 넘음) 알림 없이 돈다 — 설정 줄은 "이 휴대폰에서는 받을 수 없음" final PushMessaging pushMessaging = await FirebasePushMessaging.start( sdkInt: device.androidSdkInt, ); // 지난 실행이 받아 둔 파일(메일 첨부)과 고른 파일의 복사본(쓰기 화면의 첨부)을 지운다 — 기다리지 않는다 // (저장소가 차례를 지켜 새로 받는 파일 · 새로 고른 파일은 지우지 않는다) final DownloadedFileStore downloadedFiles = CacheDirFileStore(); unawaited(downloadedFiles.purge()); final PickedFileStore pickedFiles = PlatformPickedFileStore(); unawaited(pickedFiles.purge()); runApp( ProviderScope( // 프로바이더의 실패를 저절로 다시 하지 않는다(core/utils/provider_retry.dart) retry: noAutomaticRetry, overrides: [ tokenStoreProvider.overrideWithValue(tokenStore), userAgentProvider.overrideWithValue(device.userAgent), appVersionProvider.overrideWithValue(device.appVersion), appPackageNameProvider.overrideWithValue(device.packageName), downloadedFileStoreProvider.overrideWithValue(downloadedFiles), pickedFileStoreProvider.overrideWithValue(pickedFiles), pushMessagingProvider.overrideWithValue(pushMessaging), ], child: const App(), ), ); }