diff --git a/integration_test/cef_dns_real_test.dart b/integration_test/cef_dns_real_test.dart index b46952c..1a9aadf 100644 --- a/integration_test/cef_dns_real_test.dart +++ b/integration_test/cef_dns_real_test.dart @@ -45,13 +45,13 @@ void main() { final answered = []; final logs = []; final g = NetGuard.instance - ..config = (() => c.settings.dnsConfig) + ..config = (() => c.settings.network.config) ..log = logs.add; g.resolver.onAnswer = (h, s) => answered.add('$h@$s'); // 원인 가르기: JJ_CEF_NO_PROXY=1 이면 프록시 없이 (Chrome 엔진만) final noProxy = Platform.environment['JJ_CEF_NO_PROXY'] == '1'; - if (noProxy) c.settings.dnsMode = 'system'; - expect(c.settings.dnsMode, noProxy ? 'system' : 'custom'); + if (noProxy) c.settings.network.mode = 'system'; + expect(c.settings.network.mode, noProxy ? 'system' : 'custom'); await tester.runAsync(g.ensure); HttpOverrides.global = JjHttpOverrides(); Future wait(int ms) async { diff --git a/integration_test/dns_block_real_test.dart b/integration_test/dns_block_real_test.dart index 61bfe2e..331fac2 100644 --- a/integration_test/dns_block_real_test.dart +++ b/integration_test/dns_block_real_test.dart @@ -26,12 +26,12 @@ void main() { final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings ..webViewDataDir = p.join(data, 'webview') - ..dnsMode = 'custom' - ..dnsPrimary = '192.0.2.1' - ..dnsSecondary = ''; + ..network.mode = 'custom' + ..network.primary = '192.0.2.1' + ..network.secondary = ''; final logs = []; final g = NetGuard.instance - ..config = (() => c.settings.dnsConfig) + ..config = (() => c.settings.network.config) ..log = logs.add; await tester.runAsync(g.ensure); Future wait(int ms) async { @@ -69,6 +69,6 @@ void main() { await tester.pumpWidget(const SizedBox()); await wait(1000); - g.config = () => c.settings.dnsConfig; + g.config = () => c.settings.network.config; }); } diff --git a/integration_test/magnet_real_test.dart b/integration_test/magnet_real_test.dart index 2ad85fa..644cbfe 100644 --- a/integration_test/magnet_real_test.dart +++ b/integration_test/magnet_real_test.dart @@ -66,15 +66,15 @@ void main() { final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings ..downloadRoot = dir.path - ..dnsMode = forced ? 'custom' : 'system' - ..dnsPrimary = '8.8.8.8' - ..dnsSecondary = '8.8.4.4'; + ..network.mode = forced ? 'custom' : 'system' + ..network.primary = '8.8.8.8' + ..network.secondary = '8.8.4.4'; final g = NetGuard.instance - ..config = (() => c.settings.dnsConfig) + ..config = (() => c.settings.network.config) ..log = log; await tester.runAsync(g.ensure); addTearDown(() async { - c.settings.dnsMode = 'system'; + c.settings.network.mode = 'system'; await g.ensure(); }); final d = DownloadManager(backends: [Aria2Backend(aria2c: aria2c)], settings: () => c.settings); diff --git a/integration_test/tor_dns_real_test.dart b/integration_test/tor_dns_real_test.dart index ab3ee8b..dbf5b3e 100644 --- a/integration_test/tor_dns_real_test.dart +++ b/integration_test/tor_dns_real_test.dart @@ -37,12 +37,12 @@ void main() { final logs = []; final answered = []; final g = NetGuard.instance - ..config = (() => c.settings.dnsConfig) + ..config = (() => c.settings.network.config) ..log = logs.add; g.resolver.onAnswer = (h, s) => answered.add('$h@$s'); TorService.instance.log = logs.add; - expect(c.settings.dnsMode, 'custom'); - expect(c.settings.dnsPrimary, '8.8.8.8'); + expect(c.settings.network.mode, 'custom'); + expect(c.settings.network.primary, '8.8.8.8'); await tester.runAsync(g.ensure); HttpOverrides.global = JjHttpOverrides(); Future wait(int ms) async { @@ -97,8 +97,8 @@ void main() { // 3. 닿지 않는 DNS (TEST-NET) → 기기 DNS 로 바꾸지 않고 실패 + 알림 c.settings - ..dnsPrimary = '192.0.2.1' - ..dnsSecondary = ''; + ..network.primary = '192.0.2.1' + ..network.secondary = ''; g.resolver.clearCache(); final err = await tester.runAsync(() async { final cl = HttpClient(); @@ -117,8 +117,8 @@ void main() { expect(err, contains('502')); expect(g.failure.value, isNotNull); c.settings - ..dnsPrimary = '8.8.8.8' - ..dnsSecondary = '8.8.4.4'; + ..network.primary = '8.8.8.8' + ..network.secondary = '8.8.4.4'; g.resolver.clearCache(); // 4. Tor 컴포넌트 받기 (공식 번들 · SHA-256) → Tor 화면 → check.torproject.org diff --git a/lib/app/settings.dart b/lib/app/settings.dart index 1e4afb7..227b8cf 100644 --- a/lib/app/settings.dart +++ b/lib/app/settings.dart @@ -4,7 +4,6 @@ import 'package:path/path.dart' as p; import 'components.dart'; import '../core/reader_sources.dart' show defaultImageExtensions; -import '../core/dns_resolver.dart'; import '../core/download_detect.dart'; import '../core/encode_options.dart'; import '../core/playlist.dart'; @@ -17,11 +16,13 @@ import '../services/app_shell.dart' show appIconOf; import '../core/remote_idle.dart'; import 'settings/records.dart'; import 'settings/settings_group.dart'; +import 'settings/network_settings.dart'; import 'settings/explorer_settings.dart'; export 'settings/records.dart'; export 'settings/settings_group.dart'; export 'settings/settings_store.dart'; +export 'settings/network_settings.dart'; export 'settings/explorer_settings.dart'; /// 환경 설정 (settings.json 에 저장) @@ -157,13 +158,7 @@ class AppSettings { bool webJavaScript = true; // ── 네트워크 · DNS (사용자 요청 10/10: "DNS 주소를 강제로 내가 설정한 주소로", 기본 8.8.8.8 · 보조 8.8.4.4 - 관리자 판단) ── - /// 'system' 기기 DNS (끄기) · 'custom' 직접 지정 (기본) · 'doh' DNS over HTTPS - String dnsMode = DnsConfig.defaultMode; - String dnsPrimary = DnsConfig.defaultPrimary; - String dnsSecondary = DnsConfig.defaultSecondary; - String dnsDohUrl = DnsConfig.defaultDohUrl; - DnsConfig get dnsConfig => DnsConfig(mode: dnsMode, primary: dnsPrimary, secondary: dnsSecondary, dohUrl: dnsDohUrl); // ── Tor 브라우저 (사용자 요청 10/10) ── /// Tor 화면의 쿠키 · 기록 · 캐시를 닫은 뒤에도 남기기 (기본: 닫으면 지움) @@ -507,8 +502,11 @@ class AppSettings { /// 파일 탐색기 (X-plore 참고) final explorer = ExplorerSettings(); + /// 네트워크 · DNS (사용자 요청 10/10) + final network = NetworkSettings(); + /// 설정 분야들 (설정 A) - 저마다 자기 키를 읽고 쓴다. toJson · fromJson 은 이 목록을 돌며 합치기만 한다 - List get groups => [explorer]; + List get groups => [explorer, network]; /// [plainSecrets]: 안전 저장소를 쓸 수 없을 때만 (예전 파일에 있던 비밀 값을 잃지 않게) 예전처럼 파일에 둔다 Map toJson({bool plainSecrets = false}) { @@ -570,10 +568,6 @@ class AppSettings { 'externalBrowser': externalBrowser, 'webTranslate': webTranslate, 'webJavaScript': webJavaScript, - 'dnsMode': dnsMode, - 'dnsPrimary': dnsPrimary, - 'dnsSecondary': dnsSecondary, - 'dnsDohUrl': dnsDohUrl, 'torKeepData': torKeepData, 'torIdleMinutes': torIdleMinutes, 'torHomeUrl': torHomeUrl, @@ -770,19 +764,6 @@ class AppSettings { ..externalBrowser = j['externalBrowser'] as String? ?? 'system' ..webTranslate = j['webTranslate'] as bool? ?? false ..webJavaScript = j['webJavaScript'] as bool? ?? true - // 값이 없거나 틀리면 처음 값 (사용자가 정한 기본: 직접 지정 8.8.8.8 · 8.8.4.4). 보조는 비워 둘 수 있다 - ..dnsMode = DnsConfig.modes.contains(j['dnsMode']) ? j['dnsMode'] as String : DnsConfig.defaultMode - ..dnsPrimary = j['dnsPrimary'] is String && parseDnsServer(j['dnsPrimary'] as String) != null - ? (j['dnsPrimary'] as String).trim() - : DnsConfig.defaultPrimary - ..dnsSecondary = j['dnsSecondary'] is String - ? (parseDnsServer(j['dnsSecondary'] as String) != null || (j['dnsSecondary'] as String).trim().isEmpty - ? (j['dnsSecondary'] as String).trim() - : DnsConfig.defaultSecondary) - : DnsConfig.defaultSecondary - ..dnsDohUrl = j['dnsDohUrl'] is String && isValidDohUrl(j['dnsDohUrl'] as String) - ? (j['dnsDohUrl'] as String).trim() - : DnsConfig.defaultDohUrl ..torKeepData = j['torKeepData'] == true ..torIdleMinutes = j['torIdleMinutes'] is int && (j['torIdleMinutes'] as int) >= 0 && (j['torIdleMinutes'] as int) <= 60 ? j['torIdleMinutes'] as int @@ -1027,7 +1008,7 @@ class AppSettings { if (j.isNotEmpty && !j.containsKey('swipeNav') && s.swipeNav) 'swipeNav', if (j.isNotEmpty && !j.containsKey('runInBackground') && s.runInBackground && Platform.isAndroid) 'background', // DNS 강제 (사용자 요청 10/10, 처음 값 직접 지정 8.8.8.8 · 8.8.4.4) 가 없던 판에서 올라오면 이름을 묻는 서버가 바뀐다 - 193 과 같이 한 번 알림 - if (j.isNotEmpty && !j.containsKey('dnsMode') && s.dnsMode == 'custom') 'dnsForced', + if (j.isNotEmpty && !j.containsKey('dnsMode') && s.network.mode == 'custom') 'dnsForced', // 193 · 229: 예전 판을 쓰던 사람 (설정 파일이 있는데 이 항목이 없음) 에게 복사 · 이동이 받는 쪽의 더 새 파일을 건너뛰게 바뀐 것을 한 번 if (j.isNotEmpty && !j.containsKey('copySkipNewer')) 'copySkipNewer', // 193: robocopy 를 쓰던 사람 (Windows) 에게 링크 · junction 을 따라가지 않게 (/XJ) 바뀐 것을 한 번 diff --git a/lib/app/settings/network_settings.dart b/lib/app/settings/network_settings.dart new file mode 100644 index 0000000..c6ceac9 --- /dev/null +++ b/lib/app/settings/network_settings.dart @@ -0,0 +1,43 @@ + +import '../../core/dns_resolver.dart'; +import 'settings_group.dart'; + +/// 약속 (설정 A): 환경 설정 > 네트워크 · DNS (사용자 요청 10/10) - 자기 키 (이름 · 처음 값 · 읽기 · 쓰기) 를 스스로 갖는다. +/// 설정 하나를 더할 때는 이 파일만 고친다. 저장 파일의 키 이름은 예전 그대로 (평평한 키) +class NetworkSettings implements SettingsGroup { + /// 'system' 기기 DNS (끄기) · 'custom' 직접 지정 (기본) · 'doh' DNS over HTTPS + String mode = DnsConfig.defaultMode; + + String primary = DnsConfig.defaultPrimary; + + String secondary = DnsConfig.defaultSecondary; + + String dohUrl = DnsConfig.defaultDohUrl; + + DnsConfig get config => DnsConfig(mode: mode, primary: primary, secondary: secondary, dohUrl: dohUrl); + + @override + void write(Map j, {required bool plainSecrets}) { + j['dnsMode'] = mode; + j['dnsPrimary'] = primary; + j['dnsSecondary'] = secondary; + j['dnsDohUrl'] = dohUrl; + } + + @override + void read(Map j) { + // 값이 없거나 틀리면 처음 값 (사용자가 정한 기본: 직접 지정 8.8.8.8 · 8.8.4.4). 보조는 비워 둘 수 있다 + mode = DnsConfig.modes.contains(j['dnsMode']) ? j['dnsMode'] as String : DnsConfig.defaultMode; + primary = j['dnsPrimary'] is String && parseDnsServer(j['dnsPrimary'] as String) != null + ? (j['dnsPrimary'] as String).trim() + : DnsConfig.defaultPrimary; + secondary = j['dnsSecondary'] is String + ? (parseDnsServer(j['dnsSecondary'] as String) != null || (j['dnsSecondary'] as String).trim().isEmpty + ? (j['dnsSecondary'] as String).trim() + : DnsConfig.defaultSecondary) + : DnsConfig.defaultSecondary; + dohUrl = j['dnsDohUrl'] is String && isValidDohUrl(j['dnsDohUrl'] as String) + ? (j['dnsDohUrl'] as String).trim() + : DnsConfig.defaultDohUrl; + } +} diff --git a/lib/main.dart b/lib/main.dart index 1127b7c..b5f3c44 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -312,7 +312,7 @@ Future main(List args) async { downloads.refresh(); }; downloads.useSystemDns = () async { - await controller.updateSettings((x) => x.dnsMode = 'system'); + await controller.updateSettings((x) => x.network.mode = 'system'); downloads.refresh(); }; // COM 준비 상태 지킴이: 풀려 있으면 (앱 안 브라우저가 "CoInitialize 가 호출되지 않았습니다" 로 안 뜨는 원인) @@ -468,7 +468,7 @@ Future openFromOtherApp( /// [second] (재생만 하는 새 창) 은 설정을 읽기만 한다 Future setupNetwork(AppController c, String dataDir, {bool second = false}) async { final g = NetGuard.instance - ..config = (() => c.settings.dnsConfig) + ..config = (() => c.settings.network.config) ..log = c.note; try { await g.ensure(); @@ -498,17 +498,17 @@ Future setupNetwork(AppController c, String dataDir, {bool second = false} onHide: () => unawaited(WebProxy.setForeground(false)), ); } - var last = c.settings.dnsConfig.key; + var last = c.settings.network.config.key; var lastPause = c.settings.webPauseOnLeave; c.addListener(() async { if (Platform.isAndroid && c.settings.webPauseOnLeave != lastPause) { lastPause = c.settings.webPauseOnLeave; await WebProxy.apply(); } - final now = c.settings.dnsConfig.key; + final now = c.settings.network.config.key; if (now == last) return; last = now; - c.note(trf('DNS 설정: {0}', [c.settings.dnsMode == 'system' ? tr('시스템 DNS') : c.settings.dnsConfig.label])); + c.note(trf('DNS 설정: {0}', [c.settings.network.mode == 'system' ? tr('시스템 DNS') : c.settings.network.config.label])); await g.ensure(); if (Platform.isAndroid) await WebProxy.apply(); }); @@ -528,7 +528,7 @@ void watchDnsFailure(GlobalKey messengerKey, AppControll // 사용자에게는 무엇이 안 되고 무엇을 할지만 (예외 원문은 작업 기록에 - NetGuard.reportError). // 상태가 풀리거나 같은 안내를 보이는 화면이 열리면 스스로 닫힌다 (248) content: DnsFailureNotice(failure: f), - action: (tr('시스템 DNS 로 바꾸기'), () => c.updateSettings((x) => x.dnsMode = 'system')), + action: (tr('시스템 DNS 로 바꾸기'), () => c.updateSettings((x) => x.network.mode = 'system')), ); }); } @@ -632,7 +632,7 @@ Future runAndroid(String dataDir) async { downloads.refresh(); }; downloads.useSystemDns = () async { - await controller.updateSettings((x) => x.dnsMode = 'system'); + await controller.updateSettings((x) => x.network.mode = 'system'); downloads.refresh(); }; downloads.addToEditList = controller.addDownloaded; diff --git a/lib/ui/browser_page.dart b/lib/ui/browser_page.dart index a121ca9..850b140 100644 --- a/lib/ui/browser_page.dart +++ b/lib/ui/browser_page.dart @@ -280,7 +280,7 @@ class _BrowserPageState extends State with RouteAware { Wrap(spacing: 8, runSpacing: 8, alignment: WrapAlignment.center, children: [ FilledButton( onPressed: () async { - await widget.c.updateSettings((x) => x.dnsMode = 'system'); + await widget.c.updateSettings((x) => x.network.mode = 'system'); // 새 DNS 설정이 프록시에 걸린 뒤 다시 읽는다 await Future.delayed(const Duration(milliseconds: 300)); if (mounted) retry(); diff --git a/lib/ui/downloads_page.dart b/lib/ui/downloads_page.dart index 0b0d7a6..f883617 100644 --- a/lib/ui/downloads_page.dart +++ b/lib/ui/downloads_page.dart @@ -353,7 +353,7 @@ class _DownloadRow extends StatelessWidget { child: Text(tr('자세히')), ), // 263: 아직 DNS 강제면 [시스템 DNS 로 바꾸기] (바꾼 뒤 [다시 시도] 는 사용자가 - 몰래 다시 받지 않음) - if (t.extra['dnsServer'] != null && d.useSystemDns != null && d.settings().dnsMode != 'system') + if (t.extra['dnsServer'] != null && d.useSystemDns != null && d.settings().network.mode != 'system') TextButton(style: _small, onPressed: () => d.useSystemDns!(), child: Text(tr('시스템 DNS 로 바꾸기'))), TextButton(style: _small, onPressed: () => d.resume([t]), child: Text(tr('다시 시도'))), ]) diff --git a/lib/ui/network_settings.dart b/lib/ui/network_settings.dart index 8f32731..d431c96 100644 --- a/lib/ui/network_settings.dart +++ b/lib/ui/network_settings.dart @@ -47,7 +47,7 @@ class DnsFailureLine extends StatelessWidget { TextButton( style: TextButton.styleFrom( visualDensity: VisualDensity.compact, padding: const EdgeInsets.symmetric(horizontal: 8), minimumSize: const Size(0, 36)), - onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'), + onPressed: () => c.updateSettings((x) => x.network.mode = 'system'), child: Text(tr('시스템 DNS 로 바꾸기'), style: const TextStyle(fontSize: 13)), ), ]), @@ -59,7 +59,7 @@ class DnsFailureLine extends StatelessWidget { const Icon(Icons.warning_amber_rounded, size: 18, color: Colors.orange), Text(text, style: const TextStyle(fontSize: 12, color: Colors.orange)), TextButton( - onPressed: () => c.updateSettings((x) => x.dnsMode = 'system'), + onPressed: () => c.updateSettings((x) => x.network.mode = 'system'), child: Text(tr('시스템 DNS 로 바꾸기')), ), ]), @@ -149,11 +149,11 @@ class _DnsSettingsState extends State { _testing = true; _test = null; }); - final r = DnsResolver(config: () => c.settings.dnsConfig); + final r = DnsResolver(config: () => c.settings.network.config); String? server; r.onAnswer = (_, s) => server = s; try { - final a = c.settings.dnsMode == 'system' + final a = c.settings.network.mode == 'system' ? await InternetAddress.lookup('www.google.com').then((v) { server = tr('기기 DNS'); return v; @@ -188,34 +188,34 @@ class _DnsSettingsState extends State { subtitle: Text(tr('주소 이름 (예: youtube.com) 을 찾을 때 물어볼 서버. 직접 지정하면 기기의 DNS 대신 이 서버만 씁니다. ' '서버에 닿지 않으면 기기 DNS 로 몰래 바꾸지 않고 알립니다.')), trailing: DropdownButton( - value: s.dnsMode, + value: s.network.mode, items: [ DropdownMenuItem(value: 'system', child: Text(tr('시스템 DNS (끄기)'))), DropdownMenuItem(value: 'custom', child: Text(tr('직접 지정 (기본)'))), DropdownMenuItem(value: 'doh', child: Text(tr('DNS over HTTPS'))), ], - onChanged: (v) => _save((x) => x.dnsMode = v!), + onChanged: (v) => _save((x) => x.network.mode = v!), ), ), - if (s.dnsMode != 'system') + if (s.network.mode != 'system') Padding( padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), child: Wrap(spacing: 12, runSpacing: 12, children: [ - if (s.dnsMode == 'doh') - _field(tr('DoH 주소'), s.dnsDohUrl, _dohError, hint: DnsConfig.defaultDohUrl, (v) { + if (s.network.mode == 'doh') + _field(tr('DoH 주소'), s.network.dohUrl, _dohError, hint: DnsConfig.defaultDohUrl, (v) { final ok = isValidDohUrl(v); setState(() => _dohError = ok ? null : tr('https:// 로 시작하는 주소를 넣으세요')); - if (ok) _save((x) => x.dnsDohUrl = v.trim()); + if (ok) _save((x) => x.network.dohUrl = v.trim()); }), - _field(s.dnsMode == 'doh' ? tr('DoH 서버 이름을 찾을 서버') : tr('기본 DNS'), s.dnsPrimary, _primaryError, hint: DnsConfig.defaultPrimary, (v) { + _field(s.network.mode == 'doh' ? tr('DoH 서버 이름을 찾을 서버') : tr('기본 DNS'), s.network.primary, _primaryError, hint: DnsConfig.defaultPrimary, (v) { final ok = parseDnsServer(v) != null; setState(() => _primaryError = ok ? null : tr('IPv4 · IPv6 주소를 넣으세요 (예: 8.8.8.8)')); - if (ok) _save((x) => x.dnsPrimary = v.trim()); + if (ok) _save((x) => x.network.primary = v.trim()); }), - _field(tr('보조 DNS (비워 둘 수 있음)'), s.dnsSecondary, _secondaryError, hint: DnsConfig.defaultSecondary, (v) { + _field(tr('보조 DNS (비워 둘 수 있음)'), s.network.secondary, _secondaryError, hint: DnsConfig.defaultSecondary, (v) { final ok = v.trim().isEmpty || parseDnsServer(v) != null; setState(() => _secondaryError = ok ? null : tr('IPv4 · IPv6 주소를 넣으세요 (예: 8.8.4.4)')); - if (ok) _save((x) => x.dnsSecondary = v.trim()); + if (ok) _save((x) => x.network.secondary = v.trim()); }), ]), ), diff --git a/test/aria2_stall_test.dart b/test/aria2_stall_test.dart index af4a5b2..33c886a 100644 --- a/test/aria2_stall_test.dart +++ b/test/aria2_stall_test.dart @@ -61,7 +61,7 @@ void main() { testWidgets('멈춘 마그넷 줄: "트래커 · 피어에 닿지 않습니다" · 이유 후보 · [다시 시도] (지금 것을 지우고 새로 넣음)', (tester) async { final b = _Backend(); - final s = AppSettings()..dnsMode = 'custom'; + final s = AppSettings()..network.mode = 'custom'; final d = DownloadManager(backends: [b], settings: () => s); final t = d.add('magnet:?xt=urn:btih:7acf8fb590b2060dd9c3146ef770169d593433b0')!; await tester.pump(); diff --git a/test/browser_test.dart b/test/browser_test.dart index 6edc260..18deb1f 100644 --- a/test/browser_test.dart +++ b/test/browser_test.dart @@ -396,7 +396,7 @@ void main() { await tester.pump(); await tester.tap(find.text('시스템 DNS 로 바꾸기')); await tester.pump(const Duration(milliseconds: 400)); - expect(c.settings.dnsMode, 'system'); + expect(c.settings.network.mode, 'system'); expect(find.text(msg), findsNothing); expect(nav.reloads, 2); diff --git a/test/components_test.dart b/test/components_test.dart index 473be69..bb78825 100644 --- a/test/components_test.dart +++ b/test/components_test.dart @@ -72,7 +72,7 @@ void main() { expect(find.text('DNS 서버 (192.0.2.1) 에 닿지 않음 (01:35부터)'), findsOneWidget); await tester.tap(find.text('시스템 DNS 로 바꾸기')); await tester.pump(); - expect(c.settings.dnsMode, 'system'); + expect(c.settings.network.mode, 'system'); }); testWidgets('위쪽 이동 버튼: 설치한 화면만 · 설정을 바꾸면 바로 · 하나뿐이면 그것만', (tester) async { diff --git a/test/dns_proxy_test.dart b/test/dns_proxy_test.dart index 6fc1238..4182619 100644 --- a/test/dns_proxy_test.dart +++ b/test/dns_proxy_test.dart @@ -464,15 +464,15 @@ void main() { test('설정: 처음은 직접 지정 8.8.8.8 · 8.8.4.4, 틀린 값은 처음 값, 사용자가 고른 값은 그대로', () { final s = AppSettings(); - expect((s.dnsMode, s.dnsPrimary, s.dnsSecondary, s.dnsDohUrl), ('custom', '8.8.8.8', '8.8.4.4', 'https://dns.google/dns-query')); - expect(AppSettings.fromJson({}).dnsMode, 'custom'); + expect((s.network.mode, s.network.primary, s.network.secondary, s.network.dohUrl), ('custom', '8.8.8.8', '8.8.4.4', 'https://dns.google/dns-query')); + expect(AppSettings.fromJson({}).network.mode, 'custom'); final bad = AppSettings.fromJson({'dnsMode': 'x', 'dnsPrimary': 'dns.google', 'dnsSecondary': '1.2.3', 'dnsDohUrl': 'ftp://x'}); - expect((bad.dnsMode, bad.dnsPrimary, bad.dnsSecondary, bad.dnsDohUrl), ('custom', '8.8.8.8', '8.8.4.4', 'https://dns.google/dns-query')); + expect((bad.network.mode, bad.network.primary, bad.network.secondary, bad.network.dohUrl), ('custom', '8.8.8.8', '8.8.4.4', 'https://dns.google/dns-query')); final mine = AppSettings.fromJson( AppSettings().toJson()..addAll({'dnsMode': 'system', 'dnsPrimary': '1.1.1.1', 'dnsSecondary': '', 'dnsDohUrl': 'https://cloudflare-dns.com/dns-query'})); - expect((mine.dnsMode, mine.dnsPrimary, mine.dnsSecondary, mine.dnsDohUrl), ('system', '1.1.1.1', '', 'https://cloudflare-dns.com/dns-query')); + expect((mine.network.mode, mine.network.primary, mine.network.secondary, mine.network.dohUrl), ('system', '1.1.1.1', '', 'https://cloudflare-dns.com/dns-query')); final back = AppSettings.fromJson(mine.toJson()); - expect(back.dnsConfig.key, mine.dnsConfig.key); + expect(back.network.config.key, mine.network.config.key); // Tor 설정 처음 값 expect((s.torKeepData, s.torHomeUrl, s.torJavaScript, s.torNoticeSeen), (false, 'https://check.torproject.org/', true, false)); }); diff --git a/test/download_error_test.dart b/test/download_error_test.dart index a5eb22f..df4d3d8 100644 --- a/test/download_error_test.dart +++ b/test/download_error_test.dart @@ -135,7 +135,7 @@ void main() { final b = _Backend(tunnel); final d = DownloadManager(backends: [b], settings: () => s, readClipboard: () async => null); d.useSystemDns = () async { - s.dnsMode = 'system'; + s.network.mode = 'system'; d.refresh(); }; final t = d.addPage('https://cdn.example.com/page')!..title = '영상'; @@ -149,7 +149,7 @@ void main() { await tester.tap(find.text('시스템 DNS 로 바꾸기')); await tester.pump(); - expect(s.dnsMode, 'system'); + expect(s.network.mode, 'system'); expect(find.text('시스템 DNS 로 바꾸기'), findsNothing); expect(b.starts, 1, reason: '몰래 다시 받지 않는다'); diff --git a/test/tor_test.dart b/test/tor_test.dart index b2b3654..955f0f2 100644 --- a/test/tor_test.dart +++ b/test/tor_test.dart @@ -428,10 +428,10 @@ void main() { 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'); + expect(c.settings.network.mode, 'custom'); await t.tap(find.text('시스템 DNS 로 바꾸기')); await t.pump(); - expect(c.settings.dnsMode, 'system'); + expect(c.settings.network.mode, 'system'); g.failure.value = null; await t.pump(); expect(find.textContaining('에 닿지 않음'), findsNothing);