From cfed8fa35562144833d7bc6b6ad21ee13e9ab549 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:16:49 +0900 Subject: [PATCH] =?UTF-8?q?WIP=20145=20=EC=B4=88=EA=B8=B0=ED=99=94=20?= =?UTF-8?q?=EC=B0=BD=20=EC=BA=A1=EC=B2=98=20(ko=20=C2=B7=20en=20=C2=B7=20j?= =?UTF-8?q?a=20=C3=97=20412=20=C2=B7=20960,=20=EC=8B=9C=ED=97=98=20windows?= =?UTF-8?q?=5Freset=5Fshot):=20=EC=9E=98=EB=A6=BC=20=EC=97=86=EC=9D=8C=20?= =?UTF-8?q?=C2=B7=20=EB=AC=B8=EA=B5=AC=EB=A5=BC=20=EC=82=AC=EC=8B=A4?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20-=20SFTP=20=C2=B7=20SMB=20=C2=B7=20FTP=20?= =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=C2=B7=20=ED=82=A4?= =?UTF-8?q?=EB=8F=84=20=EC=A7=80=EC=9B=80,=20"=EC=95=B1=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=84=EC=B2=B4"=20=EB=8A=94=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=ED=83=90=EC=83=89=EA=B8=B0=20=EC=A6=90=EA=B2=A8?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=EB=8F=84=20=EC=A7=80=EC=9B=80=20(=EA=B2=80?= =?UTF-8?q?=ED=86=A0=20=EB=8C=80=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- assets/l10n/en.json | 4 +- assets/l10n/ja.json | 4 +- assets/l10n/zh-Hans.json | 4 +- integration_test/windows_reset_shot_test.dart | 94 +++++++++++++++++++ lib/ui/master_prompt.dart | 6 +- 5 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 integration_test/windows_reset_shot_test.dart diff --git a/assets/l10n/en.json b/assets/l10n/en.json index 866554c..9469ef0 100644 --- a/assets/l10n/en.json +++ b/assets/l10n/en.json @@ -352,8 +352,8 @@ "VLC 가 설치되어 있지 않습니다. 설치하면 목록에 나타납니다 (videolan.org).": "VLC is not installed. Once installed it appears in the list (videolan.org).", "VLC 로 열기": "Open with VLC", "WebDAV {0} 실패: {1} {2}{3}": "WebDAV {0} failed: {1} {2}{3}", - "WebDAV · OpenSubtitles 등. 서버 목록과 아이디는 남깁니다": "WebDAV, OpenSubtitles, etc. Server list and user names are kept", "WebDAV · OpenSubtitles 비밀번호를 이 기기의 안전 저장소에 둡니다. 끄면 저장하지 않고 (있던 것도 지움) 앱을 켤 때마다 다시 넣습니다": "Keeps WebDAV and OpenSubtitles passwords in this device's secure storage. When off, nothing is saved (existing ones are removed) and you enter them each time the app starts", + "WebDAV · SFTP · SMB · FTP · OpenSubtitles 비밀번호, SFTP 키, API 키. 서버 목록과 아이디는 남깁니다": "WebDAV, SFTP, SMB, FTP and OpenSubtitles passwords, SFTP keys and API keys. Server lists and user names are kept", "WebDAV · SFTP 는 서버에서 안의 것을 모두 읽어 오래 걸릴 수 있습니다. 분석할까요?": "WebDAV / SFTP reads everything inside from the server, which can take a long time. Analyze?", "WebDAV · SFTP 의 동영상은 MKV 목록에 넣을 수 없습니다. 먼저 이 기기로 복사하세요.": "Videos on WebDAV / SFTP can't be added to the MKV list. Copy them to this device first.", "WebDAV · SFTP 파일은 이름 · 크기 · 날짜만 봅니다": "WebDAV / SFTP files show only name, size and date", @@ -362,7 +362,6 @@ "WebDAV · SFTP: rsync 대신 앱이 직접 맞춥니다 (크기 · 바뀐 때 비교, 옵션 중 -u · --delete · --remove-source-files 를 따름).": "WebDAV / SFTP: the app syncs directly instead of rsync (compares size and modified time; follows -u, --delete and --remove-source-files).", "WebDAV 서버 \"{0}\" 을(를) 지울까요?": "Delete WebDAV server \"{0}\"?", "WebDAV 서버 고치기": "Edit WebDAV server", - "WebDAV 서버 목록과 그 저장된 비밀번호도 지워집니다. 동영상 목록 · 즐겨찾기 · 파일은 그대로입니다": "The WebDAV server list and its saved passwords are deleted too. The video list, bookmarks and files are kept", "WebDAV 서버 설정이 없습니다 ({0})": "No WebDAV server settings ({0})", "WebDAV 서버 추가": "Add WebDAV server", "WebDAV 에서 받는 중": "Downloading from WebDAV", @@ -1519,6 +1518,7 @@ "서버 ({0}) 에 연결할 수 없습니다: {1}": "Can't connect to the server ({0}): {1}", "서버 ({0}) 와의 연결이 끊겼습니다": "The connection to the server ({0}) was lost", "서버 · 서비스 (기기 밖)": "Servers · services (off device)", + "서버 목록 (WebDAV · SFTP · SMB · FTP) 과 그 비밀번호 · API 키, 파일 탐색기 즐겨찾기도 지워집니다. 동영상 목록 · 웹 즐겨찾기 · 파일은 그대로입니다": "Server lists (WebDAV, SFTP, SMB, FTP) with their passwords and API keys, and file explorer favorites, are deleted too. The video list, web bookmarks and files are kept", "서버 설정 고치기": "Edit server settings", "서버 설정과 이 기기에 저장된 비밀번호 · 개인 키 · 믿은 서버 키를 지웁니다. 서버의 파일은 그대로입니다. 이 서버를 쓰는 동기화 · 복사는 다시 넣을 때까지 연결되지 않습니다.": "Deletes the server settings and the password, private key and trusted server key saved on this device. Files on the server stay as they are. Syncs and copies that use this server won't connect until you add it again.", "서버 설정과 이 기기에 저장된 비밀번호 · 믿은 인증서를 지웁니다. 서버의 파일은 그대로입니다.": "Deletes the server settings and the password and trusted certificate saved on this device. Files on the server are not touched.", diff --git a/assets/l10n/ja.json b/assets/l10n/ja.json index 50c26a4..591f7f0 100644 --- a/assets/l10n/ja.json +++ b/assets/l10n/ja.json @@ -352,8 +352,8 @@ "VLC 가 설치되어 있지 않습니다. 설치하면 목록에 나타납니다 (videolan.org).": "VLC がインストールされていません。インストールするとリストに表示されます(videolan.org)。", "VLC 로 열기": "VLC で開く", "WebDAV {0} 실패: {1} {2}{3}": "WebDAV {0} 失敗: {1} {2}{3}", - "WebDAV · OpenSubtitles 등. 서버 목록과 아이디는 남깁니다": "WebDAV・OpenSubtitles など。サーバー一覧と ID は残します", "WebDAV · OpenSubtitles 비밀번호를 이 기기의 안전 저장소에 둡니다. 끄면 저장하지 않고 (있던 것도 지움) 앱을 켤 때마다 다시 넣습니다": "WebDAV・OpenSubtitles のパスワードをこの端末の安全な保存領域に保存します。オフにすると保存せず (既存のものも削除)、アプリを起動するたびに入力します", + "WebDAV · SFTP · SMB · FTP · OpenSubtitles 비밀번호, SFTP 키, API 키. 서버 목록과 아이디는 남깁니다": "WebDAV・SFTP・SMB・FTP・OpenSubtitles のパスワード、SFTP キー、API キー。サーバー一覧と ID は残します", "WebDAV · SFTP 는 서버에서 안의 것을 모두 읽어 오래 걸릴 수 있습니다. 분석할까요?": "WebDAV・SFTP はサーバーから中身をすべて読むため、時間がかかることがあります。分析しますか?", "WebDAV · SFTP 의 동영상은 MKV 목록에 넣을 수 없습니다. 먼저 이 기기로 복사하세요.": "WebDAV・SFTP の動画は MKV リストに追加できません。先にこの端末へコピーしてください。", "WebDAV · SFTP 파일은 이름 · 크기 · 날짜만 봅니다": "WebDAV・SFTP のファイルは名前・サイズ・日付のみ表示します", @@ -362,7 +362,6 @@ "WebDAV · SFTP: rsync 대신 앱이 직접 맞춥니다 (크기 · 바뀐 때 비교, 옵션 중 -u · --delete · --remove-source-files 를 따름).": "WebDAV・SFTP: rsync の代わりにアプリが直接同期します (サイズ・更新日時で比較、オプションのうち -u・--delete・--remove-source-files に従う)。", "WebDAV 서버 \"{0}\" 을(를) 지울까요?": "WebDAV サーバー「{0}」を削除しますか?", "WebDAV 서버 고치기": "WebDAV サーバーを編集", - "WebDAV 서버 목록과 그 저장된 비밀번호도 지워집니다. 동영상 목록 · 즐겨찾기 · 파일은 그대로입니다": "WebDAV サーバー一覧とその保存したパスワードも消えます。動画リスト・お気に入り・ファイルはそのままです", "WebDAV 서버 설정이 없습니다 ({0})": "WebDAV サーバー設定がありません ({0})", "WebDAV 서버 추가": "WebDAV サーバーを追加", "WebDAV 에서 받는 중": "WebDAV からダウンロード中", @@ -1519,6 +1518,7 @@ "서버 ({0}) 에 연결할 수 없습니다: {1}": "サーバー ({0}) に接続できません: {1}", "서버 ({0}) 와의 연결이 끊겼습니다": "サーバー ({0}) との接続が切れました", "서버 · 서비스 (기기 밖)": "サーバー・サービス (端末外)", + "서버 목록 (WebDAV · SFTP · SMB · FTP) 과 그 비밀번호 · API 키, 파일 탐색기 즐겨찾기도 지워집니다. 동영상 목록 · 웹 즐겨찾기 · 파일은 그대로입니다": "サーバー一覧 (WebDAV・SFTP・SMB・FTP) とそのパスワード・API キー、ファイルエクスプローラーのお気に入りも消えます。動画リスト・ウェブのお気に入り・ファイルはそのままです", "서버 설정 고치기": "サーバー設定を修正", "서버 설정과 이 기기에 저장된 비밀번호 · 개인 키 · 믿은 서버 키를 지웁니다. 서버의 파일은 그대로입니다. 이 서버를 쓰는 동기화 · 복사는 다시 넣을 때까지 연결되지 않습니다.": "サーバー設定と、この端末に保存されたパスワード・秘密鍵・信頼したサーバー鍵を削除します。サーバーのファイルはそのままです。このサーバーを使う同期・コピーは、再登録するまで接続されません。", "서버 설정과 이 기기에 저장된 비밀번호 · 믿은 인증서를 지웁니다. 서버의 파일은 그대로입니다.": "サーバー設定と、この端末に保存したパスワード · 信頼した証明書を削除します。サーバーのファイルはそのままです。", diff --git a/assets/l10n/zh-Hans.json b/assets/l10n/zh-Hans.json index 915a373..5c1841d 100644 --- a/assets/l10n/zh-Hans.json +++ b/assets/l10n/zh-Hans.json @@ -352,8 +352,8 @@ "VLC 가 설치되어 있지 않습니다. 설치하면 목록에 나타납니다 (videolan.org).": "未安装 VLC。安装后会出现在列表中(videolan.org)。", "VLC 로 열기": "用 VLC 打开", "WebDAV {0} 실패: {1} {2}{3}": "WebDAV {0} 失败: {1} {2}{3}", - "WebDAV · OpenSubtitles 등. 서버 목록과 아이디는 남깁니다": "WebDAV · OpenSubtitles 等。保留服务器列表和用户名", "WebDAV · OpenSubtitles 비밀번호를 이 기기의 안전 저장소에 둡니다. 끄면 저장하지 않고 (있던 것도 지움) 앱을 켤 때마다 다시 넣습니다": "将 WebDAV · OpenSubtitles 密码保存在本设备的安全存储中。关闭后不保存 (已有的也会删除),每次启动应用时重新输入", + "WebDAV · SFTP · SMB · FTP · OpenSubtitles 비밀번호, SFTP 키, API 키. 서버 목록과 아이디는 남깁니다": "WebDAV · SFTP · SMB · FTP · OpenSubtitles 密码、SFTP 密钥和 API 密钥。保留服务器列表和用户名", "WebDAV · SFTP 는 서버에서 안의 것을 모두 읽어 오래 걸릴 수 있습니다. 분석할까요?": "WebDAV · SFTP 需要从服务器读取全部内容,可能需要较长时间。要分析吗?", "WebDAV · SFTP 의 동영상은 MKV 목록에 넣을 수 없습니다. 먼저 이 기기로 복사하세요.": "无法将 WebDAV · SFTP 上的视频加入 MKV 列表。请先复制到本设备。", "WebDAV · SFTP 파일은 이름 · 크기 · 날짜만 봅니다": "WebDAV · SFTP 文件仅显示名称、大小和日期", @@ -362,7 +362,6 @@ "WebDAV · SFTP: rsync 대신 앱이 직접 맞춥니다 (크기 · 바뀐 때 비교, 옵션 중 -u · --delete · --remove-source-files 를 따름).": "WebDAV · SFTP: 由应用直接同步而非 rsync (比较大小 · 修改时间,遵循 -u · --delete · --remove-source-files)。", "WebDAV 서버 \"{0}\" 을(를) 지울까요?": "删除 WebDAV 服务器“{0}”吗?", "WebDAV 서버 고치기": "编辑 WebDAV 服务器", - "WebDAV 서버 목록과 그 저장된 비밀번호도 지워집니다. 동영상 목록 · 즐겨찾기 · 파일은 그대로입니다": "WebDAV 服务器列表及其保存的密码也会被删除。视频列表 · 收藏 · 文件保持不变", "WebDAV 서버 설정이 없습니다 ({0})": "没有 WebDAV 服务器设置({0})", "WebDAV 서버 추가": "添加 WebDAV 服务器", "WebDAV 에서 받는 중": "正在从 WebDAV 下载", @@ -1519,6 +1518,7 @@ "서버 ({0}) 에 연결할 수 없습니다: {1}": "无法连接服务器 ({0}):{1}", "서버 ({0}) 와의 연결이 끊겼습니다": "与服务器 ({0}) 的连接已断开", "서버 · 서비스 (기기 밖)": "服务器 · 服务 (设备外)", + "서버 목록 (WebDAV · SFTP · SMB · FTP) 과 그 비밀번호 · API 키, 파일 탐색기 즐겨찾기도 지워집니다. 동영상 목록 · 웹 즐겨찾기 · 파일은 그대로입니다": "服务器列表 (WebDAV · SFTP · SMB · FTP) 及其密码 · API 密钥、文件管理器收藏也会删除。视频列表 · 网页书签 · 文件保持不变", "서버 설정 고치기": "修改服务器设置", "서버 설정과 이 기기에 저장된 비밀번호 · 개인 키 · 믿은 서버 키를 지웁니다. 서버의 파일은 그대로입니다. 이 서버를 쓰는 동기화 · 복사는 다시 넣을 때까지 연결되지 않습니다.": "删除服务器设置以及本设备保存的密码、私钥和已信任的服务器密钥。服务器上的文件保持不变。使用此服务器的同步 · 复制在重新添加前无法连接。", "서버 설정과 이 기기에 저장된 비밀번호 · 믿은 인증서를 지웁니다. 서버의 파일은 그대로입니다.": "删除服务器设置以及本设备上保存的密码和已信任的证书。服务器上的文件不受影响。", diff --git a/integration_test/windows_reset_shot_test.dart b/integration_test/windows_reset_shot_test.dart new file mode 100644 index 0000000..afd553b --- /dev/null +++ b/integration_test/windows_reset_shot_test.dart @@ -0,0 +1,94 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:jj_mkvmaker/app/app_controller.dart'; +import 'package:jj_mkvmaker/app/i18n_controller.dart'; +import 'package:jj_mkvmaker/app/master_lock.dart'; +import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; +import 'package:jj_mkvmaker/platform/windows/process_media_tool.dart'; +import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'package:jj_mkvmaker/services/secret_store.dart'; +import 'package:jj_mkvmaker/ui/master_prompt.dart'; +import 'package:jj_mkvmaker/ui/theme.dart'; +import 'package:path/path.dart' as p; + +/// 145 (관리자 지시 10/19): 124 초기화 창 (최상 비밀번호 - 초기화 · 정말 초기화할까요? · 마스터를 잊었을 때) 을 +/// 크기 412 · 960, 언어 ko · en · ja 로 찍는다. 아무것도 지우지 않는다 (가짜 저장소, [초기화] 는 누르지 않음). +/// 실행: flutter test integration_test\windows_reset_shot_test.dart -d windows (JJ_SHOT_DIR 에 PNG) +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + final out = Platform.environment['JJ_SHOT_DIR'] ?? p.join(Directory.systemTemp.path, 'jj_shots_reset'); + for (final lang in ['ko', 'en', 'ja']) { + for (final (w, h) in [(412, 900), (960, 600)]) { + testWidgets('초기화 창 $lang ${w}x$h', (t) async { + t.view.physicalSize = Size(w.toDouble(), h.toDouble()); + t.view.devicePixelRatio = 1; + addTearDown(t.view.reset); + await t.runAsync(() => i18n.apply(lang, save: false)); + addTearDown(() => i18n.apply('ko', save: false)); + final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); + final lock = MasterLock(MemorySecretStore()); + await t.runAsync(() async { + await lock.load(); + await lock.setMaster('시험-마스터'); + }); + final navKey = GlobalKey(); + final shotKey = GlobalKey(); + await t.pumpWidget(RepaintBoundary( + key: shotKey, + child: MaterialApp( + theme: buildTheme(), debugShowCheckedModeBanner: false, navigatorKey: navKey, home: const Scaffold(body: SizedBox.expand())), + )); + Future settle([int n = 8]) async { + for (var i = 0; i < n; i++) { + await t.runAsync(() => Future.delayed(const Duration(milliseconds: 60))); + await t.pump(); + } + } + + Future shot(String name) async { + await settle(3); + expect(t.takeException(), isNull, reason: '$name 넘침'); + final b = shotKey.currentContext!.findRenderObject()! as RenderRepaintBoundary; + final img = await t.runAsync(() => b.toImage()); + final bytes = await t.runAsync(() => img!.toByteData(format: ui.ImageByteFormat.png)); + Directory(out).createSync(recursive: true); + File(p.join(out, 'reset_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); + } + + Future closeAll() async { + navKey.currentState!.popUntil((r) => r.isFirst); + await settle(); + } + + // ① 최상 비밀번호 - 초기화 (무엇을 초기화할지) - 셋 다 체크해 긴 설명까지 보이게 + unawaited(showSuperReset(navKey.currentContext!, c, lock)); + await settle(); + await shot('1_super'); + for (final cb in find.byType(CheckboxListTile).evaluate().toList()) { + final tile = cb.widget as CheckboxListTile; + if (tile.value != true && tile.onChanged != null) tile.onChanged!(true); + } + await settle(); + await shot('2_super_all'); + // ② 정말 초기화할까요? (한 번 더 확인) - 여기서는 [취소] + await t.tap(find.byType(FilledButton).last); + await settle(); + await shot('3_sure'); + await closeAll(); + + // ③ 마스터를 잊었을 때 (저장된 비밀번호를 지우고 마스터 초기화) - 확인 창만 + unawaited(forgotMaster(navKey.currentContext!, c, lock)); + await settle(); + await shot('4_forgot'); + await closeAll(); + expect(lock.hasMaster, isTrue, reason: '찍기만 하고 지우지 않음'); + }); + } + } +} diff --git a/lib/ui/master_prompt.dart b/lib/ui/master_prompt.dart index 616ba97..2da04d7 100644 --- a/lib/ui/master_prompt.dart +++ b/lib/ui/master_prompt.dart @@ -197,13 +197,15 @@ Future showSuperReset(BuildContext context, AppController c, MasterLock lo value: secrets, onChanged: (v) => set(() => secrets = v!), title: Text(tr('저장된 실제 비밀번호 · API 키')), - subtitle: Text(tr('WebDAV · OpenSubtitles 등. 서버 목록과 아이디는 남깁니다')), + // 145: 10/18 에 생긴 SFTP · SMB · FTP 비밀번호 · 키도 지운다 (clearStoredSecrets) + subtitle: Text(tr('WebDAV · SFTP · SMB · FTP · OpenSubtitles 비밀번호, SFTP 키, API 키. 서버 목록과 아이디는 남깁니다')), ), CheckboxListTile( value: settings, onChanged: (v) => set(() => settings = v!), title: Text(tr('앱 설정 전체 (처음 상태로)')), - subtitle: Text(tr('WebDAV 서버 목록과 그 저장된 비밀번호도 지워집니다. 동영상 목록 · 즐겨찾기 · 파일은 그대로입니다')), + // 145: 파일 탐색기 즐겨찾기 (73) 는 설정 안에 있어 함께 지워진다 - 예전 글은 "즐겨찾기는 그대로" + subtitle: Text(tr('서버 목록 (WebDAV · SFTP · SMB · FTP) 과 그 비밀번호 · API 키, 파일 탐색기 즐겨찾기도 지워집니다. 동영상 목록 · 웹 즐겨찾기 · 파일은 그대로입니다')), ), ]), ),