닿지 않는 DNS: 새 버전 확인 실패를 사용자 글로 · 안내는 닫을 때까지 · 상태를 설정 · 작업 현황에 (247 · 248 · 249)
테스터 a4 의 914 기기 확인 · 관리자 지시 (10/12, 버그 수정 · 편의): - 247: 새 버전 확인 실패가 영어 원문 (HttpException: Proxy failed to establish tunnel (502 ...)) 이던 것. DNS 강제 프록시에서 실패했으면 "DNS 서버 (…) 에 닿지 않아 새 버전을 확인하지 못했습니다" (원문은 작업 기록). - 248: [시스템 DNS 로 바꾸기] 가 붙은 안내가 12초 만에 사라지던 것 → 사용자가 닫거나 누를 때까지. - 249: 안내가 1분마다 다시 뜨던 것 → 처음 실패 때 한 번. 상태는 서버가 다시 답하거나 DNS 설정을 바꿀 때까지 환경 설정 > 네트워크 · DNS 와 작업 현황에 "DNS 서버 (…) 에 닿지 않음 (시각부터) · [시스템 DNS 로 바꾸기]". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>tor_dns
parent
893f6759ff
commit
6470368c2e
|
|
@ -144,9 +144,12 @@
|
|||
"DNS 강제 프록시를 시작하지 못했습니다: {0}": "Could not start the DNS-forcing proxy: {0}",
|
||||
"DNS 서버": "DNS server",
|
||||
"DNS 서버 ({0}) 에 닿지 않습니다: {1}": "Cannot reach the DNS server ({0}): {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 {1}": "Couldn't reach the DNS server ({0}), so {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다. 인터넷 연결이나 환경 설정 > 네트워크 · DNS 의 서버 주소를 확인하세요.": "Couldn't reach the DNS server ({0}), so the address couldn't be found. Check the internet connection or the server address in Settings > Network · DNS.",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다: {1}": "Could not look up the address because the DNS server ({0}) is unreachable: {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않음 ({1}부터)": "Can't reach DNS server ({0}) (since {1})",
|
||||
"DNS 서버 주소가 없습니다 (환경 설정 > 네트워크 · DNS)": "No DNS server address (Settings > Network · DNS)",
|
||||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "The DNS server couldn't find the address of {0}, so {1}",
|
||||
"DNS 설정: {0}": "DNS setting: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS failure ({0}): {1}",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "View DOC · DOCX · HWP · XLS · XLSX converted to PDF (downloads a converter)",
|
||||
|
|
@ -406,6 +409,7 @@
|
|||
"{0} 안의 파일": "Files in {0}",
|
||||
"{0} 에 보내는 중": "Sending to {0}",
|
||||
"{0} 에 붙여넣기 ({1}개)": "Paste into {0} ({1})",
|
||||
"{0} 에 연결하지 못해 {1} (DNS 강제 프록시)": "Couldn't connect to {0}, so {1} (forced DNS proxy)",
|
||||
"{0} 에 연결할 수 없습니다": "Cannot connect to {0}",
|
||||
"{0} 에 연결할 수 없습니다. 네트워크 · NAS 가 켜져 있는지 확인하세요.": "Cannot connect to {0}. Check that the network and NAS are on.",
|
||||
"{0} 에서 그리는 중 ({1}초)": "Drawing on {0} ({1} s)",
|
||||
|
|
@ -1135,6 +1139,7 @@
|
|||
"새 버전 v{0}": "New version v{0}",
|
||||
"새 버전 v{0} 이 있습니다": "New version v{0} is available",
|
||||
"새 버전 확인: 지금 v{0} · 최신 v{1}": "Update check: current v{0} · latest v{1}",
|
||||
"새 버전을 확인하지 못했습니다": "the update check failed.",
|
||||
"새 버전을 확인할 수 없습니다: {0}": "Cannot check for a new version: {0}",
|
||||
"새 버전이 예전 기본값을 바꿨으면 켤 때 한 번 무엇이 바뀌었는지 알려 줍니다": "If a new version changed old defaults, shows once at startup what changed",
|
||||
"새 비밀번호": "New password",
|
||||
|
|
|
|||
|
|
@ -144,9 +144,12 @@
|
|||
"DNS 강제 프록시를 시작하지 못했습니다: {0}": "DNS 強制プロキシを開始できませんでした: {0}",
|
||||
"DNS 서버": "DNS サーバー",
|
||||
"DNS 서버 ({0}) 에 닿지 않습니다: {1}": "DNS サーバー ({0}) に届きません: {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 {1}": "DNS サーバー ({0}) に接続できないため、{1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다. 인터넷 연결이나 환경 설정 > 네트워크 · DNS 의 서버 주소를 확인하세요.": "DNS サーバー ({0}) に届かず、アドレスを見つけられませんでした。インターネット接続か、環境設定 > ネットワーク · DNS のサーバーアドレスを確認してください。",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다: {1}": "DNS サーバー ({0}) に届かず、アドレスを解決できませんでした: {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않음 ({1}부터)": "DNS サーバー ({0}) に接続できません ({1} から)",
|
||||
"DNS 서버 주소가 없습니다 (환경 설정 > 네트워크 · DNS)": "DNS サーバーのアドレスがありません (環境設定 > ネットワーク・DNS)",
|
||||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "DNS サーバーが {0} のアドレスを見つけられないため、{1}",
|
||||
"DNS 설정: {0}": "DNS 設定: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS 失敗 ({0}): {1}",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "DOC・DOCX・HWP・XLS・XLSX を PDF に変換して表示 (変換ツールをダウンロード)",
|
||||
|
|
@ -406,6 +409,7 @@
|
|||
"{0} 안의 파일": "{0} 内のファイル",
|
||||
"{0} 에 보내는 중": "{0} に送信中",
|
||||
"{0} 에 붙여넣기 ({1}개)": "{0} に貼り付け ({1} 件)",
|
||||
"{0} 에 연결하지 못해 {1} (DNS 강제 프록시)": "{0} に接続できないため、{1} (DNS 強制プロキシ)",
|
||||
"{0} 에 연결할 수 없습니다": "{0} に接続できません",
|
||||
"{0} 에 연결할 수 없습니다. 네트워크 · NAS 가 켜져 있는지 확인하세요.": "{0} に接続できません。ネットワーク・NAS がオンか確認してください。",
|
||||
"{0} 에서 그리는 중 ({1}초)": "{0} で描画中 ({1} 秒)",
|
||||
|
|
@ -1135,6 +1139,7 @@
|
|||
"새 버전 v{0}": "新しいバージョン v{0}",
|
||||
"새 버전 v{0} 이 있습니다": "新しいバージョン v{0} があります",
|
||||
"새 버전 확인: 지금 v{0} · 최신 v{1}": "新しいバージョンの確認: 現在 v{0} · 最新 v{1}",
|
||||
"새 버전을 확인하지 못했습니다": "新しいバージョンを確認できませんでした。",
|
||||
"새 버전을 확인할 수 없습니다: {0}": "新しいバージョンを確認できません: {0}",
|
||||
"새 버전이 예전 기본값을 바꿨으면 켤 때 한 번 무엇이 바뀌었는지 알려 줍니다": "新しいバージョンが以前の既定値を変更した場合、起動時に一度だけ何が変わったかを知らせます",
|
||||
"새 비밀번호": "新しいパスワード",
|
||||
|
|
|
|||
|
|
@ -144,9 +144,12 @@
|
|||
"DNS 강제 프록시를 시작하지 못했습니다: {0}": "无法启动 DNS 强制代理: {0}",
|
||||
"DNS 서버": "DNS 服务器",
|
||||
"DNS 서버 ({0}) 에 닿지 않습니다: {1}": "无法连接 DNS 服务器 ({0}): {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 {1}": "无法连接 DNS 服务器 ({0}),因此{1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다. 인터넷 연결이나 환경 설정 > 네트워크 · DNS 의 서버 주소를 확인하세요.": "无法连接 DNS 服务器({0}),未能找到地址。请检查网络连接,或检查 设置 > 网络 · DNS 中的服务器地址。",
|
||||
"DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다: {1}": "无法连接 DNS 服务器 ({0}),未能解析地址: {1}",
|
||||
"DNS 서버 ({0}) 에 닿지 않음 ({1}부터)": "无法连接 DNS 服务器 ({0}) (自 {1} 起)",
|
||||
"DNS 서버 주소가 없습니다 (환경 설정 > 네트워크 · DNS)": "没有 DNS 服务器地址 (设置 > 网络 · DNS)",
|
||||
"DNS 서버가 {0} 의 주소를 찾지 못해 {1}": "DNS 服务器找不到 {0} 的地址,因此{1}",
|
||||
"DNS 설정: {0}": "DNS 设置: {0}",
|
||||
"DNS 실패 ({0}): {1}": "DNS 失败 ({0}): {1}",
|
||||
"DOC · DOCX · HWP · XLS · XLSX 를 PDF 로 바꿔 보기 (변환기를 받음)": "将 DOC · DOCX · HWP · XLS · XLSX 转为 PDF 查看 (需下载转换器)",
|
||||
|
|
@ -406,6 +409,7 @@
|
|||
"{0} 안의 파일": "{0} 中的文件",
|
||||
"{0} 에 보내는 중": "正在发送到 {0}",
|
||||
"{0} 에 붙여넣기 ({1}개)": "粘贴到 {0} ({1} 个)",
|
||||
"{0} 에 연결하지 못해 {1} (DNS 강제 프록시)": "无法连接 {0},因此{1} (强制 DNS 代理)",
|
||||
"{0} 에 연결할 수 없습니다": "无法连接到 {0}",
|
||||
"{0} 에 연결할 수 없습니다. 네트워크 · NAS 가 켜져 있는지 확인하세요.": "无法连接到 {0}。请确认网络和 NAS 已开启。",
|
||||
"{0} 에서 그리는 중 ({1}초)": "正在 {0} 上绘制 ({1} 秒)",
|
||||
|
|
@ -1135,6 +1139,7 @@
|
|||
"새 버전 v{0}": "新版本 v{0}",
|
||||
"새 버전 v{0} 이 있습니다": "有新版本 v{0}",
|
||||
"새 버전 확인: 지금 v{0} · 최신 v{1}": "检查新版本: 当前 v{0} · 最新 v{1}",
|
||||
"새 버전을 확인하지 못했습니다": "未能检查新版本。",
|
||||
"새 버전을 확인할 수 없습니다: {0}": "无法检查新版本: {0}",
|
||||
"새 버전이 예전 기본값을 바꿨으면 켤 때 한 번 무엇이 바뀌었는지 알려 줍니다": "如果新版本更改了旧的默认值,启动时提示一次更改了什么",
|
||||
"새 비밀번호": "新密码",
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@ class NetGuard {
|
|||
/// 지금 DNS 설정 (main 에서 환경 설정을 읽게 바꾼다)
|
||||
DnsConfig Function() config = () => const DnsConfig.system();
|
||||
|
||||
late final DnsResolver resolver = DnsResolver(config: () => config());
|
||||
// 249: 정한 서버가 다시 답하면 "닿지 않음" 상태를 지운다
|
||||
late final DnsResolver resolver = DnsResolver(config: () => config())..onAnswer = (_, _) => _answered();
|
||||
LocalProxy? _proxy;
|
||||
Future<int>? _starting;
|
||||
|
||||
/// DNS 서버에 닿지 않음 (화면에 알림 - [시스템 DNS 로 바꾸기])
|
||||
/// DNS 서버에 닿지 않음 (화면에 알림 - [시스템 DNS 로 바꾸기]).
|
||||
/// 249: 서버가 다시 답하거나 DNS 설정을 바꿀 때까지 남는다 - 아래 안내를 놓쳐도 환경 설정 > 네트워크 · DNS 와 작업 현황에 보인다.
|
||||
final failure = ValueNotifier<DnsFailure?>(null);
|
||||
|
||||
/// 작업 기록
|
||||
|
|
@ -47,6 +49,7 @@ class NetGuard {
|
|||
/// 설정이 강제면 프록시를 띄운다 (이미 떠 있으면 그대로). 설정을 바꾼 뒤에도 부른다
|
||||
Future<void> ensure() async {
|
||||
resolver.clearCache();
|
||||
failure.value = null; // 설정이 바뀌었다 - 새 설정으로 다시 본다
|
||||
if (!config().forced) return;
|
||||
if (port != null) return;
|
||||
_starting ??= () async {
|
||||
|
|
@ -67,17 +70,45 @@ class NetGuard {
|
|||
}
|
||||
}
|
||||
|
||||
DateTime? _lastAlert;
|
||||
DateTime? _lastLog;
|
||||
|
||||
/// 247: 프록시가 연결하지 못한 이름과 그 까닭 (앱의 HTTP 오류를 사용자 글로 바꿀 때)
|
||||
final _lastError = <String, (Object, DateTime)>{};
|
||||
|
||||
void reportError(String host, Object e) {
|
||||
if (_lastError.length > 200) _lastError.clear();
|
||||
_lastError[host.toLowerCase()] = (e, DateTime.now());
|
||||
if (e is! DnsException || !e.unreachable) return;
|
||||
log?.call(trf('DNS 실패 ({0}): {1}', [host, e]));
|
||||
final now = DateTime.now();
|
||||
// 같은 알림을 계속 띄우지 않게 (1분에 한 번)
|
||||
if (_lastAlert != null && now.difference(_lastAlert!) < const Duration(minutes: 1)) return;
|
||||
_lastAlert = now;
|
||||
// 작업 기록은 1분에 한 번 (같은 실패가 줄줄이 나지 않게)
|
||||
if (_lastLog == null || now.difference(_lastLog!) >= const Duration(minutes: 1)) {
|
||||
_lastLog = now;
|
||||
log?.call(trf('DNS 실패 ({0}): {1}', [host, e]));
|
||||
}
|
||||
// 248 · 249: 안내는 "닿지 않음" 이 처음 생길 때 한 번 (다시 답한 뒤 또 실패하면 다시). 상태는 [failure] 에 남는다
|
||||
if (failure.value != null) return;
|
||||
failure.value = DnsFailure(e.server.isEmpty ? config().label : e.server, e.message, now);
|
||||
}
|
||||
|
||||
void _answered() {
|
||||
if (failure.value != null) failure.value = null;
|
||||
}
|
||||
|
||||
/// 247: 앱의 HTTP 요청이 DNS 강제 프록시에서 실패했으면 그 까닭을 사용자 글로 ("DNS 서버 (…) 에 닿지 않아 …").
|
||||
/// 프록시 실패가 아니면 null (부르는 쪽이 원래 글을 쓴다). [what] 은 무엇을 못 했는지 ("새 버전을 확인하지 못했습니다").
|
||||
String? explain(Object e, String what) {
|
||||
if (e is! HttpException || !'$e'.contains('Proxy failed to establish tunnel')) return null;
|
||||
final host = (e.uri?.host ?? '').toLowerCase();
|
||||
final last = _lastError[host];
|
||||
final recent = last != null && DateTime.now().difference(last.$2) < const Duration(minutes: 2);
|
||||
final why = recent ? last.$1 : null;
|
||||
if (why is DnsException && why.unreachable) {
|
||||
return trf('DNS 서버 ({0}) 에 닿지 않아 {1}', [why.server.isEmpty ? config().label : why.server, what]);
|
||||
}
|
||||
if (why is DnsException) return trf('DNS 서버가 {0} 의 주소를 찾지 못해 {1}', [host, what]);
|
||||
return trf('{0} 에 연결하지 못해 {1} (DNS 강제 프록시)', [host.isEmpty ? '?' : host, what]);
|
||||
}
|
||||
|
||||
/// 이 주소는 프록시를 거치지 않는다: IP 주소 (DNS 를 묻지 않음) · 같은 집 안 이름 (LAN · NAS · Tailscale)
|
||||
static bool isDirectHost(String host) => host.isEmpty || InternetAddress.tryParse(host) != null || isLocalName(host);
|
||||
|
||||
|
|
|
|||
|
|
@ -503,9 +503,9 @@ void watchDnsFailure(GlobalKey<ScaffoldMessengerState> messengerKey, AppControll
|
|||
final f = NetGuard.instance.failure.value;
|
||||
if (f == null) return;
|
||||
messengerKey.currentState?.showSnackBar(SnackBar(
|
||||
duration: const Duration(seconds: 12),
|
||||
// 248: 버튼이 있는 안내라 사용자가 닫거나 누를 때까지 둔다 (한 번만 뜨고, 상태는 설정 · 작업 현황에 남음 - 249)
|
||||
persist: true,
|
||||
showCloseIcon: true,
|
||||
persist: false,
|
||||
// 사용자에게는 무엇이 안 되고 무엇을 할지만 (예외 원문은 작업 기록에 - NetGuard.reportError)
|
||||
content: Text(trf('DNS 서버 ({0}) 에 닿지 않아 주소를 찾지 못했습니다. 인터넷 연결이나 환경 설정 > 네트워크 · DNS 의 서버 주소를 확인하세요.',
|
||||
[f.server])),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../app/app_controller.dart';
|
||||
import '../app/net_guard.dart';
|
||||
import '../app/settings.dart';
|
||||
import '../app/tor_service.dart';
|
||||
import '../app/web_proxy.dart';
|
||||
|
|
@ -13,6 +14,34 @@ import 'setting_tile.dart';
|
|||
import 'theme.dart';
|
||||
import 'tor_page.dart' show showTorNotice;
|
||||
|
||||
/// 249: DNS 서버에 닿지 않는 동안 보이는 줄 (환경 설정 > 네트워크 · DNS · 작업 현황) - 아래 안내를 놓쳐도 찾을 수 있게.
|
||||
/// 서버가 다시 답하거나 DNS 설정을 바꾸면 사라진다.
|
||||
class DnsFailureLine extends StatelessWidget {
|
||||
final AppController c;
|
||||
const DnsFailureLine({super.key, required this.c});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => ValueListenableBuilder<DnsFailure?>(
|
||||
valueListenable: NetGuard.instance.failure,
|
||||
builder: (context, f, _) {
|
||||
if (f == null) return const SizedBox.shrink();
|
||||
String two(int x) => x.toString().padLeft(2, '0');
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Wrap(spacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [
|
||||
const Icon(Icons.warning_amber_rounded, size: 18, color: Colors.orange),
|
||||
Text(trf('DNS 서버 ({0}) 에 닿지 않음 ({1}부터)', [f.server, '${two(f.at.hour)}:${two(f.at.minute)}']),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orange)),
|
||||
TextButton(
|
||||
onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'),
|
||||
child: Text(tr('시스템 DNS 로 바꾸기')),
|
||||
),
|
||||
]),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 환경 설정 > 네트워크 · DNS (사용자 요청 10/10): DNS 서버 강제 (처음: 직접 지정 8.8.8.8 · 8.8.4.4)
|
||||
class DnsSettings extends StatefulWidget {
|
||||
final AppController c;
|
||||
|
|
@ -68,6 +97,7 @@ class _DnsSettingsState extends State<DnsSettings> {
|
|||
final s = c.settings;
|
||||
final desk = Platform.isWindows;
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||
DnsFailureLine(c: c),
|
||||
SettingTile(
|
||||
leading: const Icon(Icons.dns_outlined),
|
||||
title: Text(tr('DNS 서버')),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import '../app/ai_local.dart' show AiStore;
|
|||
import '../app/app_controller.dart';
|
||||
import '../app/copy_center.dart' show diskSpace;
|
||||
import '../app/model_backup.dart';
|
||||
import '../app/net_guard.dart';
|
||||
import '../app/version_snapshot.dart';
|
||||
import '../core/app_update.dart';
|
||||
import '../services/updater.dart' show InstallPermissionNeeded, Updater;
|
||||
|
|
@ -44,7 +45,10 @@ Future<void> checkForUpdate(BuildContext context, AppController c, {bool manual
|
|||
r = await up.latest();
|
||||
} catch (e) {
|
||||
c.note(trf('새 버전을 확인할 수 없습니다: {0}', [e]));
|
||||
if (manual) snack(trf('새 버전을 확인할 수 없습니다: {0}', [e]));
|
||||
// 247: DNS 강제 프록시에서 실패했으면 까닭을 사용자 글로 (원문은 위 작업 기록에)
|
||||
if (manual) {
|
||||
snack(NetGuard.instance.explain(e, tr('새 버전을 확인하지 못했습니다')) ?? trf('새 버전을 확인할 수 없습니다: {0}', [e]));
|
||||
}
|
||||
return;
|
||||
}
|
||||
await c.updateSettings((x) => x
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import '../services/downloader.dart';
|
|||
import 'ai_upscale_ui.dart' show openFolderInApp;
|
||||
import 'app_actions.dart';
|
||||
import 'downloads_page.dart';
|
||||
import 'network_settings.dart' show DnsFailureLine;
|
||||
import 'theme.dart';
|
||||
import '../l10n/tr.dart';
|
||||
|
||||
|
|
@ -186,6 +187,8 @@ class WorkPanel extends StatelessWidget {
|
|||
);
|
||||
|
||||
List<Widget> _jobs(BuildContext context) => [
|
||||
// 249: DNS 서버에 닿지 않음 (안내를 놓쳐도 여기서 보고 바꿀 수 있게)
|
||||
DnsFailureLine(c: c),
|
||||
_title(tr('작업')),
|
||||
// 123: AI 그림 (남은 장 · 예상 시간)
|
||||
if (AiJobs.instance.statusLine case final ai?) ...[
|
||||
|
|
|
|||
|
|
@ -460,4 +460,54 @@ void main() {
|
|||
// Tor 설정 처음 값
|
||||
expect((s.torKeepData, s.torHomeUrl, s.torJavaScript, s.torNoticeSeen), (false, 'https://check.torproject.org/', true, false));
|
||||
});
|
||||
|
||||
test('247 · 249: 닿지 않는 DNS - 앱의 HTTP 오류를 사용자 글로 · 상태는 다시 답하거나 설정을 바꿀 때까지 남음', () async {
|
||||
final g = NetGuard.instance;
|
||||
final old = HttpOverrides.current;
|
||||
HttpOverrides.global = JjHttpOverrides();
|
||||
addTearDown(() async {
|
||||
HttpOverrides.global = old;
|
||||
g.config = () => const DnsConfig.system();
|
||||
await g.ensure();
|
||||
});
|
||||
var shown = 0;
|
||||
void count() {
|
||||
if (g.failure.value != null) shown++;
|
||||
}
|
||||
|
||||
g.failure.addListener(count);
|
||||
addTearDown(() => g.failure.removeListener(count));
|
||||
g.config = () => custom('192.0.2.1');
|
||||
await g.ensure();
|
||||
expect(g.failure.value, isNull);
|
||||
// 새 버전 확인처럼 https 로 (프록시 CONNECT 가 502 → HttpException "Proxy failed to establish tunnel")
|
||||
final client = HttpClient();
|
||||
addTearDown(client.close);
|
||||
Object? err;
|
||||
try {
|
||||
await (await client.getUrl(Uri.parse('https://api.github.com/repos/x/y/releases/latest'))).close();
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
expect('$err', contains('Proxy failed to establish tunnel'));
|
||||
final text = g.explain(err!, '새 버전을 확인하지 못했습니다');
|
||||
expect(text, 'DNS 서버 (192.0.2.1) 에 닿지 않아 새 버전을 확인하지 못했습니다');
|
||||
expect(text, isNot(contains('HttpException')));
|
||||
// 프록시 실패가 아니면 원래 글 (null)
|
||||
expect(g.explain(const SocketException('x'), '새 버전을 확인하지 못했습니다'), isNull);
|
||||
|
||||
// 상태가 남고 안내는 한 번 (또 실패해도 다시 띄우지 않음)
|
||||
expect(g.failure.value?.server, '192.0.2.1');
|
||||
g.reportError('www.example.com', const DnsException('again', unreachable: true, server: '192.0.2.1'));
|
||||
expect(shown, 1);
|
||||
// 서버가 다시 답하면 지운다
|
||||
g.resolver.onAnswer?.call('www.example.com', '192.0.2.1');
|
||||
expect(g.failure.value, isNull);
|
||||
g.reportError('www.example.com', const DnsException('again', unreachable: true, server: '192.0.2.1'));
|
||||
expect(shown, 2);
|
||||
// DNS 설정을 바꾸면 지운다
|
||||
g.config = () => const DnsConfig.system();
|
||||
await g.ensure();
|
||||
expect(g.failure.value, isNull);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||
import 'package:jj_mkvmaker/app/app_controller.dart';
|
||||
import 'package:jj_mkvmaker/app/component_store.dart';
|
||||
import 'package:jj_mkvmaker/app/components.dart';
|
||||
import 'package:jj_mkvmaker/app/net_guard.dart';
|
||||
import 'package:jj_mkvmaker/app/settings.dart';
|
||||
import 'package:jj_mkvmaker/app/tor_bundle.dart';
|
||||
import 'package:jj_mkvmaker/app/tor_service.dart';
|
||||
|
|
@ -362,6 +363,24 @@ void main() {
|
|||
expect(find.textContaining('Tor 대기 중'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('249: DNS 서버에 닿지 않는 동안 환경 설정 > 네트워크 · DNS 에 상태 줄 · [시스템 DNS 로 바꾸기]', (t) async {
|
||||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||||
final g = NetGuard.instance;
|
||||
addTearDown(() => g.failure.value = null);
|
||||
await t.pumpWidget(MaterialApp(home: Scaffold(body: SingleChildScrollView(child: DnsSettings(c: c)))));
|
||||
expect(find.textContaining('에 닿지 않음'), findsNothing);
|
||||
g.failure.value = DnsFailure('192.0.2.1', 'x', DateTime(2026, 10, 12, 9, 5));
|
||||
await t.pump();
|
||||
expect(find.text('DNS 서버 (192.0.2.1) 에 닿지 않음 (09:05부터)'), findsOneWidget);
|
||||
expect(c.settings.dnsMode, 'custom');
|
||||
await t.tap(find.text('시스템 DNS 로 바꾸기'));
|
||||
await t.pump();
|
||||
expect(c.settings.dnsMode, 'system');
|
||||
g.failure.value = null;
|
||||
await t.pump();
|
||||
expect(find.textContaining('에 닿지 않음'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('파일 링크를 누르면 받지 않고 이유를 알린다 (아무 반응 없음이 아니게)', (t) async {
|
||||
final loads = <String>[];
|
||||
final hosts = <TorViewHost>[];
|
||||
|
|
|
|||
Loading…
Reference in New Issue