Files
rup/flutter/lib/main.dart
T
ttipo 65c2016ab5 chore(flutter): 출시 준비 — 앱 이름·패키지 ID·아이콘·시작 화면·서명·서버 주소 확인
템플릿 기본값(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>
2026-10-11 23:42:45 +09:00

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(),
),
);
}