/// 약속: Windows · Android 가 같이 하는 시작 단계와 다운로드 연결. /// [startCore] 는 저장소 위치 (컴포넌트 · AI · 버전별 설정 보관) → 설정 읽기 → DNS 강제 · Tor → 마스터 잠금 → rsync · /// 실시간 동기화 → 화면 언어 → 즐겨찾기 차례로 준비한다 (인터넷 · 저장된 비밀번호를 쓰는 것보다 먼저 네트워크 · 잠금). /// [createDownloads] 는 다운로드 목록을 만들고 알림 · 다 받은 동영상을 MKV 목록에 넣기 · 설정 바꾸기를 잇는다. library; import 'package:flutter/material.dart'; import '../app/ai_local.dart'; import '../app/app_controller.dart'; import '../app/bookmarks_controller.dart'; import '../app/component_store.dart'; import '../app/download_manager.dart'; import '../app/live_sync.dart'; import '../app/version_snapshot.dart'; import '../l10n/tr.dart'; import '../app/i18n_controller.dart'; import '../ui/added_to_mkv_notice.dart'; import '../ui/master_prompt.dart'; import 'startup_helpers.dart'; /// [startCore] 가 준비한 것 typedef StartedCore = ({LiveSync live, BookmarksController bookmarks}); /// [sharedSnapshots]: 버전별 설정 보관을 함께 둘 공용 폴더 (Android - 앱을 지웠다 다시 설치해도 남게). /// [afterLanguage]: 화면 언어를 정한 바로 뒤 (즐겨찾기 전) 에 할 것 (Android: 화면 방향 · 앱 아이콘) Future startCore(AppController controller, String dataDir, {String? sharedSnapshots, Future Function()? afterLanguage}) async { ComponentStore.dataDirectory = dataDir; AiStore.instance = AiStore(dataDir); // 123 · 121: AI 모델 · 엔진 (앱 데이터 폴더의 ai) AiStore.log = controller.note; VersionSnapshot.instance = VersionSnapshot(dataDir, sharedDir: sharedSnapshots); await controller.init(); await setupNetwork(controller, dataDir); // DNS 강제 · Tor (인터넷을 쓰는 다른 것보다 먼저) await setupMasterLock(controller); // 124: 저장된 비밀번호를 쓰기 전에 (실시간 동기화보다 먼저) // 실시간 동기화 (환경 설정 > 파일 탐색기): 앱이 켜져 있는 동안. 다시 켤 때 바로 / 골라서 / 시작 안 함 await findBundledRsync(); // 앱에 들어 있는 rsync final live = LiveSync(controller)..start(hold: controller.settings.copy.liveSyncOnStart != 'auto'); // 화면 언어 (환경 설정 > 화면 언어) i18n.init(controller, dataDir); await i18n.apply(controller.settings.display.language, save: false); await afterLanguage?.call(); final bookmarks = BookmarksController(); await bookmarks.load(); return (live: live, bookmarks: bookmarks); } DownloadManager createDownloads(AppController controller, {required GlobalKey messengerKey, required GlobalKey navigatorKey}) { final services = controller.services; final downloads = DownloadManager( backends: services.createDownloadBackends?.call(() => controller.settings) ?? const [], settings: () => controller.settings, ); // 클립보드 · 브라우저로 추가된 다운로드 알림 downloads.onAdded.listen((t) => messengerKey.currentState ?.showSnackBar(SnackBar(content: Text(trf('다운로드 추가: {0}', [t.source]))))); // 다 받은 동영상 → 편집 목록 (설정에서 끌 수 있음) downloads.onFinished.listen((t) async { if (!controller.settings.download.addFinished) return; final files = DownloadManager.videoFilesOf(t); if (files.isEmpty) return; final n = await controller.addDownloaded(files); // MKV 만들기 목록으로 넘어갔으므로 다운로드 목록에서는 뺀다 (받은 파일은 그대로) downloads.dropFromList(t); // 줄이 사라진 이유와 [보기] (MKV 화면 · 그 동영상) showAddedToMkvNotice(messengerKey, navigatorKey, controller, title: t.title, files: files, added: n); }); downloads.setAutoAdd = (on) async { await controller.updateSettings((x) => x.download.addFinished = on); downloads.refresh(); }; downloads.useSystemDns = () async { await controller.updateSettings((x) => x.network.mode = 'system'); downloads.refresh(); }; downloads.addToEditList = controller.addDownloaded; downloads.log = controller.note; return downloads; }