Files
arasystem/flutter/lib/main.dart
T
ttipo 3a126bdf83 feat(flutter): 메일 쓰기 화면 2차 — 첨부 고르기 · 올리기를 더한다
[파일 첨부]가 안드로이드 고르는 창(권한 없음)을 연다. 고른 파일은 앱 임시 폴더에
복사해 두고 그 복사본을 multipart 로 둘씩 올린다 — 올리기에 실패하거나 서버가 첨부를
찾지 못해도(MAIL_004) 다시 고르지 않고 다시 올리려고.

- 사전 검사 · 보내기 막기는 웹과 같은 차례, 한도는 GET /api/mail-quota
- 기기가 같은 차례로 미리 걸러 넣을 파일만 복사한다(content:// 만, 판정은 Dart 가 다시)
- 다 올리면 서버가 정리한 이름 · 크기로 싣는다(이름 255자 — 웹과 같다)
- MAIL_004 뒤 다시 올릴 수 없는 파일은 빼기 전까지 저장 · 보내기를 막는다
- 가져오는 · 올리는 동안 [보내기]를 막고(가져오기는 10분 시한), 올리는 중 나가기는 따로 묻는다
- 화면이 끝나거나 직원이 바뀌거나 앱을 띄울 때 복사본을 지운다

리뷰(M1~M4 · L 다섯 · 다시 본 리뷰의 L 하나)를 고쳤다. 시험 690 → 750.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 04:19:57 +09:00

67 lines
2.7 KiB
Dart

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/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<void> 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 userAgent}) device =
await loadAppDeviceInfo();
// 지난 실행이 받아 둔 파일(메일 첨부)과 고른 파일의 복사본(쓰기 화면의 첨부)을 지운다 — 기다리지 않는다
// (저장소가 차례를 지켜 새로 받는 파일 · 새로 고른 파일은 지우지 않는다)
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),
downloadedFileStoreProvider.overrideWithValue(downloadedFiles),
pickedFileStoreProvider.overrideWithValue(pickedFiles),
],
child: const App(),
),
);
}