generated from ttipo/project-base
65c2016ab5
템플릿 기본값(tma_app · com.example)으로 남아 있던 앱 정체성과 출시 빌드 설정을 갖춘다. - 앱 이름 rup, 패키지(번들) ID com.ttipo.rup (Android·iOS — 스토어에 올린 뒤에는 바꿀 수 없다). 웹 제목도 rup - 앱 아이콘: 브랜드 주황 + 흰 워드마크 (원본 branding/, flutter_launcher_icons 로 크기별 생성 · Android 적응형 아이콘) - 앱이 뜨는 동안의 화면을 첫 화면(스플래시)과 같은 노란색으로 — 흰 화면이 번쩍이지 않게 (Android 12+ 포함, iOS) - Android 출시 서명: android/key.properties(커밋 안 함, 예시 key.properties.example). 없으면 경고와 함께 디버그 키 - 서버 주소는 --dart-define=API_URL 이 .env 보다 먼저. 출시 빌드가 http·개발용 주소를 가리키면 시작하지 않는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
2.0 KiB
Dart
51 lines
2.0 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:tma_app/app.dart';
|
|
import 'package:tma_app/core/api/dio_provider.dart';
|
|
import 'package:tma_app/core/api/session_store.dart';
|
|
import 'package:tma_app/core/config/app_config.dart';
|
|
import 'package:tma_app/core/storage/preferences_provider.dart';
|
|
import 'package:tma_app/shared/widgets/rup_toast.dart';
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// dotenv 로드 — .env 파일이 없으면 기본값으로 동작
|
|
try {
|
|
await dotenv.load(fileName: '.env');
|
|
} catch (_) {
|
|
// .env 파일이 없는 경우 무시 (기본값 사용)
|
|
}
|
|
|
|
// 출시 빌드가 개발 서버·평문 http 를 가리키면 바로 멈춘다 — 사용자 기기에서 조용히 모든 요청이 실패하는 것보다 낫다
|
|
if (kReleaseMode && readDataMode() == DataMode.api) {
|
|
final problem = releaseApiUrlProblem(readApiBaseUrl());
|
|
if (problem != null) throw StateError(problem);
|
|
}
|
|
|
|
// 시안은 세로 화면 전용이다
|
|
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
|
|
|
// 진입 화면 결정에 필요한 저장값을 첫 프레임 전에 읽어 둔다
|
|
final prefs = await SharedPreferences.getInstance();
|
|
// 로그인 세션(토큰) — 서버 모드에서만 secure storage 를 쓴다
|
|
final session = readDataMode() == DataMode.api
|
|
? await SessionStore.load(const SecureTokenVault())
|
|
: SessionStore(MemoryTokenVault());
|
|
|
|
runApp(
|
|
ProviderScope(
|
|
overrides: [
|
|
sharedPreferencesProvider.overrideWithValue(prefs),
|
|
sessionStoreProvider.overrideWithValue(session),
|
|
apiErrorReporterProvider.overrideWith(apiErrorToastReporter),
|
|
],
|
|
child: const RupApp(),
|
|
),
|
|
);
|
|
}
|