import 'dart:async'; import 'package:flutter/material.dart'; import '../../app/app_controller.dart'; import '../../app/download_manager.dart'; import '../../l10n/tr.dart'; import '../../services/downloader.dart' show DownloadState; import '../confirm.dart'; import '../downloads_page.dart'; import '../notice.dart'; import '../settings_page.dart'; import '../tor_page.dart'; import 'web_nav.dart'; /// Tor 브라우저로: 켜져 있으면 Tor 화면, 아니면 짧은 안내와 [환경 설정 > 컴포넌트] Future openTorOrExplain(BuildContext context, AppController c) async { if (c.settings.display.components.contains('tor')) { await TorPage.open(Navigator.of(context), c: c); return; } final go = await showDialog( context: context, builder: (ctx) => AlertDialog( scrollable: true, title: Text(tr('Tor 브라우저')), content: Text(tr('Tor 브라우저는 페이지를 Tor 로 열어 사이트가 이 기기의 주소를 알 수 없게 합니다 (쿠키 · 기록은 따로, 닫으면 지움). ' '환경 설정 > 컴포넌트 에서 켜면 이 브라우저 옆에 Tor 화면이 생깁니다.')), actions: [ TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(tr('닫기'))), FilledButton(onPressed: () => Navigator.pop(ctx, true), child: Text(tr('환경 설정 > 컴포넌트'))), ], ), ); if (go == true && context.mounted) { await Navigator.push(context, MaterialPageRoute(builder: (_) => SettingsPage(c: c, initialGroup: 'components'))); } } /// 53: 쿠키 · 방문 기록 지우기 (확인 뒤). 다운로드용으로 내보낸 쿠키 파일도 지우고 지금 페이지를 다시 읽는다 Future confirmClearBrowserData(BuildContext context, {required WebNav? nav, required String dataDir}) async { final ok = await confirmAction( context, title: tr('쿠키 · 방문 기록 지우기'), body: tr('앱 안 브라우저의 쿠키 (로그인) · 사이트 데이터 · 캐시 · 방문 기록과, 다운로드용으로 내보낸 쿠키 파일을 지웁니다. ' '사이트에 다시 로그인해야 합니다. 즐겨찾기는 그대로입니다.'), ok: tr('지우기'), ); if (!ok || !context.mounted) return; try { await nav?.clearData(); } catch (_) {} await deleteExportedCookies(dataDir); if (!context.mounted) return; ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(tr('쿠키 · 방문 기록을 지웠습니다.')))); unawaited(nav?.reload()); } /// 27: 이 페이지를 다운로드 목록에 넣는다 (yt-dlp 가 지원하면 받고, 아니면 다운로드 목록에 이유가 보인다). /// 로그인 쿠키를 먼저 내보내 yt-dlp 가 같은 로그인으로 받도록 하고, 받기 준비가 끝날 때까지 알림을 띄워 둔다 Future addPageDownload(BuildContext context, DownloadManager d, {required WebNav? nav, required String url, required String title}) async { try { await nav?.exportCookies(); } catch (_) {} if (!context.mounted) return; final t = d.addPage(url); final m = ScaffoldMessenger.of(context); if (t == null) { m.showSnackBar(SnackBar(content: Text(tr('이미 받는 중이거나 받을 수 없는 주소입니다.')))); return; } // 알림은 앱 전체에 떠 있으므로 이 브라우저 화면이 아니라 앱의 Navigator 로 연다 // (화면을 오가 이 브라우저 화면이 닫혀도 "목록 보기" 가 된다) final navigator = Navigator.of(context); // 받기 준비가 끝날 때까지 두고 아래 check 가 닫는다 ([✕] 로 바로 닫기) final bar = showNotice(m, life: NoticeLife.untilClosed, text: trf('다운로드 추가: {0}', [title.isEmpty ? url : title]), action: (tr('목록 보기'), () => DownloadsPage.open(navigator, d)))!; // 받기 준비가 끝나면 (진행률이 나오거나 · 끝 · 실패 · 취소 · 목록에서 지움) 알림을 닫는다 void check() { final ready = !d.tasks.contains(t) || t.progress != null || (t.state != DownloadState.queued && t.state != DownloadState.downloading); if (ready) { d.removeListener(check); bar.close(); } } d.addListener(check); unawaited(bar.closed.then((_) => d.removeListener(check))); }