WIP 412 캡처의 잘림: 서버 창 칸 이름은 짧게 · 설명은 helper, 해시 비교 칸, 날짜 고르기, 갈 곳 막대는 가운데 줄임 (검토 대기)
관리자 지시 (10/18, next e8baa84 캡처에서 찾은 ①~④, 회귀 아님):
① FTP · SFTP · SMB · WebDAV 서버 창: "이름 (탭에 보임, 비우면 주소)" · "시작 폴더 (비우면 …)" · "도메인 · 작업 그룹 (보통 비움)" 이 en 412 에서 잘렸다
→ 칸 이름은 "이름" · "시작 폴더" · "도메인 · 작업 그룹", 설명은 helper (3줄까지).
② 해시 창 비교 칸 → "비교할 해시" + helper "받은 곳에서 알려 준 해시를 붙여넣으세요".
③ 일괄 이름 바꾸기 날짜 고르기: 고른 뒤 상자에는 짧게 ("날짜: 찍은 때" · "날짜: 바뀐 때"), 펼친 목록은 긴 설명 그대로.
④ 한 창 갈 곳 막대: "갈 곳:" 은 늘 보이고 폴더 이름이 길면 가운데를 줄인다 (middleEllipsis · textWidth - path_label.dart). 전체 경로는 길게 눌러 · 마우스를 올려.
확인: integration_test/windows_trunc_shot_test.dart (새, 서버 창 4개 위 · 아래, 412/960 x ko/en/ja) · windows_ftp · windows_p3 · windows_xplore_tools · windows_xplore 캡처 통과
(release\test\shots_trunc), explorer · explorer_webdav · batch_rename · file_tools · ftp · smb · smb_find 시험 통과, analyze 문제 없음, l10n 빠짐 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
trunc_fix
parent
e8baa846bb
commit
53a74183a7
|
|
@ -639,6 +639,7 @@
|
||||||
"가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})",
|
"가져온 즐겨찾기 ({0})": "Imported bookmarks ({0})",
|
||||||
"가져올 즐겨찾기가 없습니다.": "No bookmarks to import.",
|
"가져올 즐겨찾기가 없습니다.": "No bookmarks to import.",
|
||||||
"간격": "Step",
|
"간격": "Step",
|
||||||
|
"갈 곳: {0}": "To: {0}",
|
||||||
"감지한 언어: {0} (자동 감지)": "Detected language: {0} (auto-detect)",
|
"감지한 언어: {0} (자동 감지)": "Detected language: {0} (auto-detect)",
|
||||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language",
|
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "Detected language: {0} - if it is wrong, make them again with another language",
|
||||||
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "Downloaded only if the detected language differs from the subtitle language {0}",
|
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "Downloaded only if the detected language differs from the subtitle language {0}",
|
||||||
|
|
@ -737,6 +738,7 @@
|
||||||
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "Files downloaded to shared folders (videos, images, etc.)",
|
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "Files downloaded to shared folders (videos, images, etc.)",
|
||||||
"공유": "Share",
|
"공유": "Share",
|
||||||
"공유 (다른 앱으로 보내기)": "Share (send to another app)",
|
"공유 (다른 앱으로 보내기)": "Share (send to another app)",
|
||||||
|
"공유 안의 폴더 · 비우면 공유의 맨 위": "A folder inside the share · empty = top of the share",
|
||||||
"공유 이름": "Share name",
|
"공유 이름": "Share name",
|
||||||
"공유 중": "Sharing",
|
"공유 중": "Sharing",
|
||||||
"공유 창을 열 수 없습니다.": "Can't open the share sheet.",
|
"공유 창을 열 수 없습니다.": "Can't open the share sheet.",
|
||||||
|
|
@ -852,6 +854,7 @@
|
||||||
"나중에": "Later",
|
"나중에": "Later",
|
||||||
"날짜": "Date",
|
"날짜": "Date",
|
||||||
"날짜: 바뀐 때": "Date: modified",
|
"날짜: 바뀐 때": "Date: modified",
|
||||||
|
"날짜: 찍은 때": "Date: taken",
|
||||||
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "Date: taken (photos; otherwise modified)",
|
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "Date: taken (photos; otherwise modified)",
|
||||||
"남는 것": "What stays",
|
"남는 것": "What stays",
|
||||||
"남은 {0}장": "{0} left",
|
"남은 {0}장": "{0} left",
|
||||||
|
|
@ -1033,6 +1036,7 @@
|
||||||
"덮어쓴 파일은 되돌릴 수 없습니다.": "Overwritten files can't be restored.",
|
"덮어쓴 파일은 되돌릴 수 없습니다.": "Overwritten files can't be restored.",
|
||||||
"덮어씁니다": "overwrites it",
|
"덮어씁니다": "overwrites it",
|
||||||
"덴마크어": "Danish",
|
"덴마크어": "Danish",
|
||||||
|
"도메인 · 작업 그룹": "Domain / workgroup",
|
||||||
"도메인 · 작업 그룹 (보통 비움)": "Domain / workgroup (usually empty)",
|
"도메인 · 작업 그룹 (보통 비움)": "Domain / workgroup (usually empty)",
|
||||||
"독일어": "German",
|
"독일어": "German",
|
||||||
"돌아가기": "Go back",
|
"돌아가기": "Go back",
|
||||||
|
|
@ -1295,6 +1299,7 @@
|
||||||
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "Copy downloaded AI models ({0}) to Download/JJ_MKVMaker and restore them after reinstalling (needs {0} more space for a while)",
|
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "Copy downloaded AI models ({0}) to Download/JJ_MKVMaker and restore them after reinstalling (needs {0} more space for a while)",
|
||||||
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "Downloaded AI models (images · subtitles) - must be downloaded again (about {0})",
|
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "Downloaded AI models (images · subtitles) - must be downloaded again (about {0})",
|
||||||
"받은 AI 자막 모델": "Downloaded AI subtitle models",
|
"받은 AI 자막 모델": "Downloaded AI subtitle models",
|
||||||
|
"받은 곳에서 알려 준 해시를 붙여넣으세요": "Paste the hash published by the source",
|
||||||
"받은 동영상을 편집 목록에 추가: {0}": "Added the received video to the edit list: {0}",
|
"받은 동영상을 편집 목록에 추가: {0}": "Added the received video to the edit list: {0}",
|
||||||
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "Temporary files left from installing updates · required programs · the Chrome engine",
|
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "Temporary files left from installing updates · required programs · the Chrome engine",
|
||||||
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "Translate received subtitles to Korean and add them too (when there are no Korean subtitles)",
|
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "Translate received subtitles to Korean and add them too (when there are no Korean subtitles)",
|
||||||
|
|
@ -1362,6 +1367,7 @@
|
||||||
"보조 DNS (비워 둘 수 있음)": "Secondary DNS (may be empty)",
|
"보조 DNS (비워 둘 수 있음)": "Secondary DNS (may be empty)",
|
||||||
"보통": "Normal",
|
"보통": "Normal",
|
||||||
"보통 (0.25, 기본)": "Normal (0.25, default)",
|
"보통 (0.25, 기본)": "Normal (0.25, default)",
|
||||||
|
"보통 비워 둡니다": "Usually left empty",
|
||||||
"보통: {0}": "Normal: {0}",
|
"보통: {0}": "Normal: {0}",
|
||||||
"복사": "Copy",
|
"복사": "Copy",
|
||||||
"복사 (붙여넣기로)": "Copy (to paste)",
|
"복사 (붙여넣기로)": "Copy (to paste)",
|
||||||
|
|
@ -1412,6 +1418,7 @@
|
||||||
"비공개 · 회원 전용 영상입니다.": "This is a private · members-only video.",
|
"비공개 · 회원 전용 영상입니다.": "This is a private · members-only video.",
|
||||||
"비교하지 못했습니다: {0}": "Couldn't compare: {0}",
|
"비교하지 못했습니다: {0}": "Couldn't compare: {0}",
|
||||||
"비교할 값 붙여넣기 (받은 곳의 해시)": "Paste a value to compare (hash from the source)",
|
"비교할 값 붙여넣기 (받은 곳의 해시)": "Paste a value to compare (hash from the source)",
|
||||||
|
"비교할 해시": "Hash to compare",
|
||||||
"비밀번호": "Password",
|
"비밀번호": "Password",
|
||||||
"비밀번호 (개인 키만 쓰면 비움)": "Password (leave empty if using only a private key)",
|
"비밀번호 (개인 키만 쓰면 비움)": "Password (leave empty if using only a private key)",
|
||||||
"비밀번호 (선택)": "Password (optional)",
|
"비밀번호 (선택)": "Password (optional)",
|
||||||
|
|
@ -1440,7 +1447,9 @@
|
||||||
"비어 있습니다": "Empty",
|
"비어 있습니다": "Empty",
|
||||||
"비어 있음": "Empty",
|
"비어 있음": "Empty",
|
||||||
"비우기": "Empty",
|
"비우기": "Empty",
|
||||||
|
"비우면 로그인한 곳 · 예: /volume1/video · 탭의 맨 위가 됩니다": "Empty = where you log in · e.g. /volume1/video · becomes the top of the tab",
|
||||||
"비우면 지움": "Empty = remove",
|
"비우면 지움": "Empty = remove",
|
||||||
|
"비우면 홈 폴더 · 예: /volume1/video · 탭의 맨 위가 됩니다": "Empty = home folder · e.g. /volume1/video · becomes the top of the tab",
|
||||||
"빈 이름": "Empty name",
|
"빈 이름": "Empty name",
|
||||||
"빈 폴더 {0}개 지움": "Deleted {0} empty folders",
|
"빈 폴더 {0}개 지움": "Deleted {0} empty folders",
|
||||||
"빈 폴더 그대로": "Leave empty folders",
|
"빈 폴더 그대로": "Leave empty folders",
|
||||||
|
|
@ -1615,6 +1624,7 @@
|
||||||
"시작 · 웹 브라우저": "Startup · web browser",
|
"시작 · 웹 브라우저": "Startup · web browser",
|
||||||
"시작 메뉴에 등록": "Add to Start menu",
|
"시작 메뉴에 등록": "Add to Start menu",
|
||||||
"시작 안 함 (모니터링에서 시작)": "Don't start (start from Monitor)",
|
"시작 안 함 (모니터링에서 시작)": "Don't start (start from Monitor)",
|
||||||
|
"시작 폴더": "Start folder",
|
||||||
"시작 폴더 (공유 안, 비우면 맨 위)": "Start folder (inside the share, top if empty)",
|
"시작 폴더 (공유 안, 비우면 맨 위)": "Start folder (inside the share, top if empty)",
|
||||||
"시작 폴더 (비우면 로그인한 곳)": "Start folder (empty = where you log in)",
|
"시작 폴더 (비우면 로그인한 곳)": "Start folder (empty = where you log in)",
|
||||||
"시작 폴더 (비우면 홈 폴더)": "Start folder (home folder if empty)",
|
"시작 폴더 (비우면 홈 폴더)": "Start folder (home folder if empty)",
|
||||||
|
|
@ -2532,6 +2542,7 @@
|
||||||
"탐색기에서 동영상을 열 때": "When opening a video from Explorer",
|
"탐색기에서 동영상을 열 때": "When opening a video from Explorer",
|
||||||
"탐색기에서 연 동영상을 재생할 창": "Window to play videos opened from Explorer",
|
"탐색기에서 연 동영상을 재생할 창": "Window to play videos opened from Explorer",
|
||||||
"태국어": "Thai",
|
"태국어": "Thai",
|
||||||
|
"탭에 보입니다 · 비우면 주소": "Shown on the tab · address if empty",
|
||||||
"터키어": "Turkish",
|
"터키어": "Turkish",
|
||||||
"토": "Sat",
|
"토": "Sat",
|
||||||
"토렌트 · 마그넷 다운로드": "Torrent · magnet download",
|
"토렌트 · 마그넷 다운로드": "Torrent · magnet download",
|
||||||
|
|
|
||||||
|
|
@ -639,6 +639,7 @@
|
||||||
"가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})",
|
"가져온 즐겨찾기 ({0})": "取り込んだブックマーク({0})",
|
||||||
"가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。",
|
"가져올 즐겨찾기가 없습니다.": "取り込むブックマークがありません。",
|
||||||
"간격": "間隔",
|
"간격": "間隔",
|
||||||
|
"갈 곳: {0}": "移動先: {0}",
|
||||||
"감지한 언어: {0} (자동 감지)": "検出した言語: {0} (自動検出)",
|
"감지한 언어: {0} (자동 감지)": "検出した言語: {0} (自動検出)",
|
||||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください",
|
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "検出した言語: {0} - 違っていれば別の言語で作り直してください",
|
||||||
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "検出した言語が作成する言語と異なる場合のみダウンロード {0}",
|
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "検出した言語が作成する言語と異なる場合のみダウンロード {0}",
|
||||||
|
|
@ -737,6 +738,7 @@
|
||||||
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "共有フォルダーにダウンロードしたファイル (動画・画像など)",
|
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "共有フォルダーにダウンロードしたファイル (動画・画像など)",
|
||||||
"공유": "共有",
|
"공유": "共有",
|
||||||
"공유 (다른 앱으로 보내기)": "共有 (他のアプリに送る)",
|
"공유 (다른 앱으로 보내기)": "共有 (他のアプリに送る)",
|
||||||
|
"공유 안의 폴더 · 비우면 공유의 맨 위": "共有内のフォルダー · 空なら共有の一番上",
|
||||||
"공유 이름": "共有名",
|
"공유 이름": "共有名",
|
||||||
"공유 중": "共有中",
|
"공유 중": "共有中",
|
||||||
"공유 창을 열 수 없습니다.": "共有画面を開けません。",
|
"공유 창을 열 수 없습니다.": "共有画面を開けません。",
|
||||||
|
|
@ -852,6 +854,7 @@
|
||||||
"나중에": "後で",
|
"나중에": "後で",
|
||||||
"날짜": "日付",
|
"날짜": "日付",
|
||||||
"날짜: 바뀐 때": "日付: 更新日時",
|
"날짜: 바뀐 때": "日付: 更新日時",
|
||||||
|
"날짜: 찍은 때": "日付: 撮影日時",
|
||||||
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "日付: 撮影日時 (写真、なければ更新日時)",
|
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "日付: 撮影日時 (写真、なければ更新日時)",
|
||||||
"남는 것": "残るもの",
|
"남는 것": "残るもの",
|
||||||
"남은 {0}장": "残り {0} 枚",
|
"남은 {0}장": "残り {0} 枚",
|
||||||
|
|
@ -1033,6 +1036,7 @@
|
||||||
"덮어쓴 파일은 되돌릴 수 없습니다.": "上書きしたファイルは元に戻せません。",
|
"덮어쓴 파일은 되돌릴 수 없습니다.": "上書きしたファイルは元に戻せません。",
|
||||||
"덮어씁니다": "上書きします",
|
"덮어씁니다": "上書きします",
|
||||||
"덴마크어": "デンマーク語",
|
"덴마크어": "デンマーク語",
|
||||||
|
"도메인 · 작업 그룹": "ドメイン・ワークグループ",
|
||||||
"도메인 · 작업 그룹 (보통 비움)": "ドメイン・ワークグループ (通常は空欄)",
|
"도메인 · 작업 그룹 (보통 비움)": "ドメイン・ワークグループ (通常は空欄)",
|
||||||
"독일어": "ドイツ語",
|
"독일어": "ドイツ語",
|
||||||
"돌아가기": "戻る",
|
"돌아가기": "戻る",
|
||||||
|
|
@ -1295,6 +1299,7 @@
|
||||||
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "ダウンロードした AI モデル ({0}) を Download/JJ_MKVMaker にコピーし、再インストール後に復元する (一時的に {0} 余分に必要)",
|
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "ダウンロードした AI モデル ({0}) を Download/JJ_MKVMaker にコピーし、再インストール後に復元する (一時的に {0} 余分に必要)",
|
||||||
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "ダウンロードした AI モデル (画像・字幕) - 再ダウンロードが必要です (約 {0})",
|
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "ダウンロードした AI モデル (画像・字幕) - 再ダウンロードが必要です (約 {0})",
|
||||||
"받은 AI 자막 모델": "ダウンロード済みの AI 字幕モデル",
|
"받은 AI 자막 모델": "ダウンロード済みの AI 字幕モデル",
|
||||||
|
"받은 곳에서 알려 준 해시를 붙여넣으세요": "入手元が示したハッシュを貼り付けてください",
|
||||||
"받은 동영상을 편집 목록에 추가: {0}": "受け取った動画を編集リストに追加: {0}",
|
"받은 동영상을 편집 목록에 추가: {0}": "受け取った動画を編集リストに追加: {0}",
|
||||||
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "更新・必須プログラム・Chrome エンジンのインストールで残った一時ファイル",
|
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "更新・必須プログラム・Chrome エンジンのインストールで残った一時ファイル",
|
||||||
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "受け取った字幕を韓国語に翻訳して一緒に追加(韓国語字幕がないとき)",
|
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "受け取った字幕を韓国語に翻訳して一緒に追加(韓国語字幕がないとき)",
|
||||||
|
|
@ -1362,6 +1367,7 @@
|
||||||
"보조 DNS (비워 둘 수 있음)": "代替 DNS (空欄可)",
|
"보조 DNS (비워 둘 수 있음)": "代替 DNS (空欄可)",
|
||||||
"보통": "普通",
|
"보통": "普通",
|
||||||
"보통 (0.25, 기본)": "普通 (0.25、既定)",
|
"보통 (0.25, 기본)": "普通 (0.25、既定)",
|
||||||
|
"보통 비워 둡니다": "通常は空欄",
|
||||||
"보통: {0}": "普通: {0}",
|
"보통: {0}": "普通: {0}",
|
||||||
"복사": "コピー",
|
"복사": "コピー",
|
||||||
"복사 (붙여넣기로)": "コピー (貼り付け用)",
|
"복사 (붙여넣기로)": "コピー (貼り付け用)",
|
||||||
|
|
@ -1412,6 +1418,7 @@
|
||||||
"비공개 · 회원 전용 영상입니다.": "非公開・メンバー限定の動画です。",
|
"비공개 · 회원 전용 영상입니다.": "非公開・メンバー限定の動画です。",
|
||||||
"비교하지 못했습니다: {0}": "比較できませんでした: {0}",
|
"비교하지 못했습니다: {0}": "比較できませんでした: {0}",
|
||||||
"비교할 값 붙여넣기 (받은 곳의 해시)": "比較する値を貼り付け (入手元のハッシュ)",
|
"비교할 값 붙여넣기 (받은 곳의 해시)": "比較する値を貼り付け (入手元のハッシュ)",
|
||||||
|
"비교할 해시": "比較するハッシュ",
|
||||||
"비밀번호": "パスワード",
|
"비밀번호": "パスワード",
|
||||||
"비밀번호 (개인 키만 쓰면 비움)": "パスワード (秘密鍵だけを使う場合は空欄)",
|
"비밀번호 (개인 키만 쓰면 비움)": "パスワード (秘密鍵だけを使う場合は空欄)",
|
||||||
"비밀번호 (선택)": "パスワード(任意)",
|
"비밀번호 (선택)": "パスワード(任意)",
|
||||||
|
|
@ -1440,7 +1447,9 @@
|
||||||
"비어 있습니다": "空です",
|
"비어 있습니다": "空です",
|
||||||
"비어 있음": "空",
|
"비어 있음": "空",
|
||||||
"비우기": "空にする",
|
"비우기": "空にする",
|
||||||
|
"비우면 로그인한 곳 · 예: /volume1/video · 탭의 맨 위가 됩니다": "空ならログインした場所 · 例: /volume1/video · タブの一番上になります",
|
||||||
"비우면 지움": "空なら削除",
|
"비우면 지움": "空なら削除",
|
||||||
|
"비우면 홈 폴더 · 예: /volume1/video · 탭의 맨 위가 됩니다": "空ならホームフォルダー · 例: /volume1/video · タブの一番上になります",
|
||||||
"빈 이름": "空の名前",
|
"빈 이름": "空の名前",
|
||||||
"빈 폴더 {0}개 지움": "空フォルダー {0} 個を削除",
|
"빈 폴더 {0}개 지움": "空フォルダー {0} 個を削除",
|
||||||
"빈 폴더 그대로": "空フォルダーはそのまま",
|
"빈 폴더 그대로": "空フォルダーはそのまま",
|
||||||
|
|
@ -1615,6 +1624,7 @@
|
||||||
"시작 · 웹 브라우저": "起動・ウェブブラウザー",
|
"시작 · 웹 브라우저": "起動・ウェブブラウザー",
|
||||||
"시작 메뉴에 등록": "スタートメニューに登録",
|
"시작 메뉴에 등록": "スタートメニューに登録",
|
||||||
"시작 안 함 (모니터링에서 시작)": "開始しない (モニタリングで開始)",
|
"시작 안 함 (모니터링에서 시작)": "開始しない (モニタリングで開始)",
|
||||||
|
"시작 폴더": "開始フォルダー",
|
||||||
"시작 폴더 (공유 안, 비우면 맨 위)": "開始フォルダー (共有内、空欄なら最上位)",
|
"시작 폴더 (공유 안, 비우면 맨 위)": "開始フォルダー (共有内、空欄なら最上位)",
|
||||||
"시작 폴더 (비우면 로그인한 곳)": "開始フォルダー (空欄ならログインした場所)",
|
"시작 폴더 (비우면 로그인한 곳)": "開始フォルダー (空欄ならログインした場所)",
|
||||||
"시작 폴더 (비우면 홈 폴더)": "開始フォルダー (空欄ならホームフォルダー)",
|
"시작 폴더 (비우면 홈 폴더)": "開始フォルダー (空欄ならホームフォルダー)",
|
||||||
|
|
@ -2532,6 +2542,7 @@
|
||||||
"탐색기에서 동영상을 열 때": "エクスプローラーで動画を開いたとき",
|
"탐색기에서 동영상을 열 때": "エクスプローラーで動画を開いたとき",
|
||||||
"탐색기에서 연 동영상을 재생할 창": "エクスプローラーで開いた動画を再生するウィンドウ",
|
"탐색기에서 연 동영상을 재생할 창": "エクスプローラーで開いた動画を再生するウィンドウ",
|
||||||
"태국어": "タイ語",
|
"태국어": "タイ語",
|
||||||
|
"탭에 보입니다 · 비우면 주소": "タブに表示 · 空ならアドレス",
|
||||||
"터키어": "トルコ語",
|
"터키어": "トルコ語",
|
||||||
"토": "土",
|
"토": "土",
|
||||||
"토렌트 · 마그넷 다운로드": "トレント・マグネットのダウンロード",
|
"토렌트 · 마그넷 다운로드": "トレント・マグネットのダウンロード",
|
||||||
|
|
|
||||||
|
|
@ -639,6 +639,7 @@
|
||||||
"가져온 즐겨찾기 ({0})": "导入的书签({0})",
|
"가져온 즐겨찾기 ({0})": "导入的书签({0})",
|
||||||
"가져올 즐겨찾기가 없습니다.": "没有可导入的书签。",
|
"가져올 즐겨찾기가 없습니다.": "没有可导入的书签。",
|
||||||
"간격": "间隔",
|
"간격": "间隔",
|
||||||
|
"갈 곳: {0}": "目标: {0}",
|
||||||
"감지한 언어: {0} (자동 감지)": "检测到的语言:{0}(自动检测)",
|
"감지한 언어: {0} (자동 감지)": "检测到的语言:{0}(自动检测)",
|
||||||
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成",
|
"감지한 언어: {0} - 틀렸으면 다른 언어로 다시 만드세요": "检测到的语言:{0} - 如有误,请用其他语言重新生成",
|
||||||
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "仅当检测到的语言与要生成的语言不同时下载 {0}",
|
"감지한 원어가 만들 언어와 다를 때만 내려받기 {0}": "仅当检测到的语言与要生成的语言不同时下载 {0}",
|
||||||
|
|
@ -737,6 +738,7 @@
|
||||||
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "下载到公共文件夹的文件 (视频、图片等)",
|
"공용 폴더에 받은 파일 (동영상 · 그림 등)": "下载到公共文件夹的文件 (视频、图片等)",
|
||||||
"공유": "分享",
|
"공유": "分享",
|
||||||
"공유 (다른 앱으로 보내기)": "分享 (发送到其他应用)",
|
"공유 (다른 앱으로 보내기)": "分享 (发送到其他应用)",
|
||||||
|
"공유 안의 폴더 · 비우면 공유의 맨 위": "共享内的文件夹 · 为空则为共享的最上层",
|
||||||
"공유 이름": "共享名称",
|
"공유 이름": "共享名称",
|
||||||
"공유 중": "共享中",
|
"공유 중": "共享中",
|
||||||
"공유 창을 열 수 없습니다.": "无法打开分享窗口。",
|
"공유 창을 열 수 없습니다.": "无法打开分享窗口。",
|
||||||
|
|
@ -852,6 +854,7 @@
|
||||||
"나중에": "以后再说",
|
"나중에": "以后再说",
|
||||||
"날짜": "日期",
|
"날짜": "日期",
|
||||||
"날짜: 바뀐 때": "日期: 修改时间",
|
"날짜: 바뀐 때": "日期: 修改时间",
|
||||||
|
"날짜: 찍은 때": "日期: 拍摄时间",
|
||||||
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "日期: 拍摄时间 (照片; 否则为修改时间)",
|
"날짜: 찍은 때 (사진, 없으면 바뀐 때)": "日期: 拍摄时间 (照片; 否则为修改时间)",
|
||||||
"남는 것": "保留的内容",
|
"남는 것": "保留的内容",
|
||||||
"남은 {0}장": "剩余 {0} 张",
|
"남은 {0}장": "剩余 {0} 张",
|
||||||
|
|
@ -1033,6 +1036,7 @@
|
||||||
"덮어쓴 파일은 되돌릴 수 없습니다.": "被覆盖的文件无法恢复。",
|
"덮어쓴 파일은 되돌릴 수 없습니다.": "被覆盖的文件无法恢复。",
|
||||||
"덮어씁니다": "覆盖",
|
"덮어씁니다": "覆盖",
|
||||||
"덴마크어": "丹麦语",
|
"덴마크어": "丹麦语",
|
||||||
|
"도메인 · 작업 그룹": "域 · 工作组",
|
||||||
"도메인 · 작업 그룹 (보통 비움)": "域 · 工作组 (通常留空)",
|
"도메인 · 작업 그룹 (보통 비움)": "域 · 工作组 (通常留空)",
|
||||||
"독일어": "德语",
|
"독일어": "德语",
|
||||||
"돌아가기": "返回",
|
"돌아가기": "返回",
|
||||||
|
|
@ -1295,6 +1299,7 @@
|
||||||
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "将已下载的 AI 模型 ({0}) 复制到 Download/JJ_MKVMaker,重新安装后恢复 (暂时需要额外 {0})",
|
"받은 AI 모델 ({0}) 을 Download/JJ_MKVMaker 에 복사해 두었다가 다시 설치한 뒤 되살리기 (잠시 {0} 더 필요)": "将已下载的 AI 模型 ({0}) 复制到 Download/JJ_MKVMaker,重新安装后恢复 (暂时需要额外 {0})",
|
||||||
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "已下载的 AI 模型 (图片 · 字幕) - 需要重新下载 (约 {0})",
|
"받은 AI 모델 (그림 · 자막) - 다시 받아야 합니다 (약 {0})": "已下载的 AI 模型 (图片 · 字幕) - 需要重新下载 (约 {0})",
|
||||||
"받은 AI 자막 모델": "已下载的 AI 字幕模型",
|
"받은 AI 자막 모델": "已下载的 AI 字幕模型",
|
||||||
|
"받은 곳에서 알려 준 해시를 붙여넣으세요": "粘贴来源提供的哈希",
|
||||||
"받은 동영상을 편집 목록에 추가: {0}": "已将收到的视频加入编辑列表: {0}",
|
"받은 동영상을 편집 목록에 추가: {0}": "已将收到的视频加入编辑列表: {0}",
|
||||||
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "安装更新 · 必需程序 · Chrome 引擎后残留的临时文件",
|
"받은 업데이트 · 필수 프로그램 · Chrome 엔진을 설치하고 남은 임시 파일": "安装更新 · 必需程序 · Chrome 引擎后残留的临时文件",
|
||||||
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "将收到的字幕翻译成韩语并一并添加(没有韩语字幕时)",
|
"받은 자막을 한국어로 번역해 함께 추가 (한국어 자막이 없을 때)": "将收到的字幕翻译成韩语并一并添加(没有韩语字幕时)",
|
||||||
|
|
@ -1362,6 +1367,7 @@
|
||||||
"보조 DNS (비워 둘 수 있음)": "备用 DNS (可留空)",
|
"보조 DNS (비워 둘 수 있음)": "备用 DNS (可留空)",
|
||||||
"보통": "普通",
|
"보통": "普通",
|
||||||
"보통 (0.25, 기본)": "普通 (0.25,默认)",
|
"보통 (0.25, 기본)": "普通 (0.25,默认)",
|
||||||
|
"보통 비워 둡니다": "通常留空",
|
||||||
"보통: {0}": "普通:{0}",
|
"보통: {0}": "普通:{0}",
|
||||||
"복사": "复制",
|
"복사": "复制",
|
||||||
"복사 (붙여넣기로)": "复制 (用于粘贴)",
|
"복사 (붙여넣기로)": "复制 (用于粘贴)",
|
||||||
|
|
@ -1412,6 +1418,7 @@
|
||||||
"비공개 · 회원 전용 영상입니다.": "这是私享 · 会员专享视频。",
|
"비공개 · 회원 전용 영상입니다.": "这是私享 · 会员专享视频。",
|
||||||
"비교하지 못했습니다: {0}": "无法比较: {0}",
|
"비교하지 못했습니다: {0}": "无法比较: {0}",
|
||||||
"비교할 값 붙여넣기 (받은 곳의 해시)": "粘贴要比较的值 (来源处的哈希)",
|
"비교할 값 붙여넣기 (받은 곳의 해시)": "粘贴要比较的值 (来源处的哈希)",
|
||||||
|
"비교할 해시": "要比较的哈希",
|
||||||
"비밀번호": "密码",
|
"비밀번호": "密码",
|
||||||
"비밀번호 (개인 키만 쓰면 비움)": "密码 (仅使用私钥时留空)",
|
"비밀번호 (개인 키만 쓰면 비움)": "密码 (仅使用私钥时留空)",
|
||||||
"비밀번호 (선택)": "密码(可选)",
|
"비밀번호 (선택)": "密码(可选)",
|
||||||
|
|
@ -1440,7 +1447,9 @@
|
||||||
"비어 있습니다": "空",
|
"비어 있습니다": "空",
|
||||||
"비어 있음": "空",
|
"비어 있음": "空",
|
||||||
"비우기": "清空",
|
"비우기": "清空",
|
||||||
|
"비우면 로그인한 곳 · 예: /volume1/video · 탭의 맨 위가 됩니다": "为空则为登录位置 · 例: /volume1/video · 成为标签的最上层",
|
||||||
"비우면 지움": "留空则删除",
|
"비우면 지움": "留空则删除",
|
||||||
|
"비우면 홈 폴더 · 예: /volume1/video · 탭의 맨 위가 됩니다": "为空则为主文件夹 · 例: /volume1/video · 成为标签的最上层",
|
||||||
"빈 이름": "空名称",
|
"빈 이름": "空名称",
|
||||||
"빈 폴더 {0}개 지움": "已删除 {0} 个空文件夹",
|
"빈 폴더 {0}개 지움": "已删除 {0} 个空文件夹",
|
||||||
"빈 폴더 그대로": "保留空文件夹",
|
"빈 폴더 그대로": "保留空文件夹",
|
||||||
|
|
@ -1615,6 +1624,7 @@
|
||||||
"시작 · 웹 브라우저": "启动 · 网页浏览器",
|
"시작 · 웹 브라우저": "启动 · 网页浏览器",
|
||||||
"시작 메뉴에 등록": "添加到开始菜单",
|
"시작 메뉴에 등록": "添加到开始菜单",
|
||||||
"시작 안 함 (모니터링에서 시작)": "不开始 (在监控中开始)",
|
"시작 안 함 (모니터링에서 시작)": "不开始 (在监控中开始)",
|
||||||
|
"시작 폴더": "起始文件夹",
|
||||||
"시작 폴더 (공유 안, 비우면 맨 위)": "起始文件夹 (共享内,留空则为最上层)",
|
"시작 폴더 (공유 안, 비우면 맨 위)": "起始文件夹 (共享内,留空则为最上层)",
|
||||||
"시작 폴더 (비우면 로그인한 곳)": "起始文件夹 (留空则为登录位置)",
|
"시작 폴더 (비우면 로그인한 곳)": "起始文件夹 (留空则为登录位置)",
|
||||||
"시작 폴더 (비우면 홈 폴더)": "起始文件夹 (留空则为主目录)",
|
"시작 폴더 (비우면 홈 폴더)": "起始文件夹 (留空则为主目录)",
|
||||||
|
|
@ -2532,6 +2542,7 @@
|
||||||
"탐색기에서 동영상을 열 때": "从资源管理器打开视频时",
|
"탐색기에서 동영상을 열 때": "从资源管理器打开视频时",
|
||||||
"탐색기에서 연 동영상을 재생할 창": "播放从资源管理器打开的视频的窗口",
|
"탐색기에서 연 동영상을 재생할 창": "播放从资源管理器打开的视频的窗口",
|
||||||
"태국어": "泰语",
|
"태국어": "泰语",
|
||||||
|
"탭에 보입니다 · 비우면 주소": "显示在标签上 · 为空则用地址",
|
||||||
"터키어": "土耳其语",
|
"터키어": "土耳其语",
|
||||||
"토": "六",
|
"토": "六",
|
||||||
"토렌트 · 마그넷 다운로드": "种子 · 磁力链接下载",
|
"토렌트 · 마그넷 다운로드": "种子 · 磁力链接下载",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
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/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/ui/ftp_settings.dart';
|
||||||
|
import 'package:jj_mkvmaker/ui/sftp_settings.dart';
|
||||||
|
import 'package:jj_mkvmaker/ui/smb_settings.dart';
|
||||||
|
import 'package:jj_mkvmaker/ui/theme.dart';
|
||||||
|
import 'package:jj_mkvmaker/ui/webdav_settings.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
/// 관리자 지시 (10/18): 412 캡처의 잘림 고침 확인 - FTP · SFTP · SMB · WebDAV 서버 추가 창 (칸 이름은 짧게, 설명은 helper).
|
||||||
|
/// 크기 412 · 960, 언어 ko · en · ja. 실행: flutter test integration_test\windows_trunc_shot_test.dart -d windows
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
final out = Platform.environment['JJ_SHOT_DIR'] ?? p.join(Directory.systemTemp.path, 'jj_shots_trunc');
|
||||||
|
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 navKey = GlobalKey<NavigatorState>();
|
||||||
|
final shotKey = GlobalKey();
|
||||||
|
await t.pumpWidget(RepaintBoundary(
|
||||||
|
key: shotKey,
|
||||||
|
child: MaterialApp(
|
||||||
|
theme: buildTheme(), debugShowCheckedModeBanner: false, navigatorKey: navKey, home: const Scaffold(body: SizedBox.expand())),
|
||||||
|
));
|
||||||
|
Future<void> settle([int n = 8]) async {
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 60)));
|
||||||
|
await t.pump();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> shot(String name) async {
|
||||||
|
await settle(3);
|
||||||
|
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, 'trunc_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final (name, open) in <(String, void Function(BuildContext))>[
|
||||||
|
('ftp', (ctx) => editFtpServer(ctx, c)),
|
||||||
|
('sftp', (ctx) => editSftpServer(ctx, c)),
|
||||||
|
('smb', (ctx) => editSmbServer(ctx, c)),
|
||||||
|
('webdav', (ctx) => editDavServer(ctx, c)),
|
||||||
|
]) {
|
||||||
|
open(navKey.currentContext!);
|
||||||
|
await settle();
|
||||||
|
await shot(name);
|
||||||
|
// 창 아래쪽 (시작 폴더 칸) 도
|
||||||
|
final scroll = find.descendant(of: find.byType(AlertDialog), matching: find.byType(Scrollable));
|
||||||
|
if (scroll.evaluate().isNotEmpty) {
|
||||||
|
await t.drag(scroll.first, const Offset(0, -600));
|
||||||
|
await settle(4);
|
||||||
|
await shot('${name}_bottom');
|
||||||
|
}
|
||||||
|
navKey.currentState!.popUntil((r) => r.isFirst);
|
||||||
|
await settle(4);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -202,6 +202,11 @@ class _BatchRenameDialogState extends State<_BatchRenameDialog> {
|
||||||
child: DropdownButton<String>(
|
child: DropdownButton<String>(
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
value: _dateSource,
|
value: _dateSource,
|
||||||
|
// 412 캡처 (10/18): 고른 뒤 상자에는 짧게 (펼친 목록은 긴 설명 그대로)
|
||||||
|
selectedItemBuilder: (_) => [
|
||||||
|
Text(tr('날짜: 찍은 때'), maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||||
|
Text(tr('날짜: 바뀐 때'), maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||||
|
],
|
||||||
items: [
|
items: [
|
||||||
DropdownMenuItem(value: 'photo', child: Text(tr('날짜: 찍은 때 (사진, 없으면 바뀐 때)'), overflow: TextOverflow.ellipsis)),
|
DropdownMenuItem(value: 'photo', child: Text(tr('날짜: 찍은 때 (사진, 없으면 바뀐 때)'), overflow: TextOverflow.ellipsis)),
|
||||||
DropdownMenuItem(value: 'modified', child: Text(tr('날짜: 바뀐 때'), overflow: TextOverflow.ellipsis)),
|
DropdownMenuItem(value: 'modified', child: Text(tr('날짜: 바뀐 때'), overflow: TextOverflow.ellipsis)),
|
||||||
|
|
|
||||||
|
|
@ -2157,11 +2157,17 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
const Icon(Icons.arrow_forward, size: 18, color: JjColors.accent),
|
const Icon(Icons.arrow_forward, size: 18, color: JjColors.accent),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
|
// 412 캡처 (10/18): "갈 곳:" 은 늘 보이고, 폴더 이름이 길면 가운데를 줄인다 (전체 경로는 길게 눌러 · 마우스를 올려)
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: _displayPath(t.current),
|
message: _displayPath(t.current),
|
||||||
child: Text(trf('복사 · 이동 갈 곳: {0}', [_folderName(t.current)]),
|
triggerMode: TooltipTriggerMode.longPress,
|
||||||
maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12.5)),
|
child: LayoutBuilder(builder: (context, box) {
|
||||||
|
const style = TextStyle(fontSize: 12.5);
|
||||||
|
final label = trf('갈 곳: {0}', ['']);
|
||||||
|
final room = box.maxWidth - textWidth(context, label, style);
|
||||||
|
return Text('$label${middleEllipsis(context, _folderName(t.current), style, room)}', maxLines: 1, overflow: TextOverflow.clip, style: style);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ Future<void> showFileHash(BuildContext context, String path) async {
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
TextField(
|
TextField(
|
||||||
controller: compare,
|
controller: compare,
|
||||||
decoration: InputDecoration(labelText: tr('비교할 값 붙여넣기 (받은 곳의 해시)'), isDense: true),
|
decoration: InputDecoration(labelText: tr('비교할 해시'), helperText: tr('받은 곳에서 알려 준 해시를 붙여넣으세요'), helperMaxLines: 3, isDense: true),
|
||||||
onChanged: (_) => set(() {}),
|
onChanged: (_) => set(() {}),
|
||||||
),
|
),
|
||||||
if (match != null)
|
if (match != null)
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ Future<FtpServer?> editFtpServer(BuildContext context, AppController c, {FtpServ
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 520,
|
width: 520,
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름 (탭에 보임, 비우면 주소)'))),
|
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름'), helperText: tr('탭에 보입니다 · 비우면 주소'), helperMaxLines: 3)),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
|
@ -265,7 +265,7 @@ Future<FtpServer?> editFtpServer(BuildContext context, AppController c, {FtpServ
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: root,
|
controller: root,
|
||||||
decoration: InputDecoration(labelText: tr('시작 폴더 (비우면 로그인한 곳)'), helperText: tr('예: /volume1/video · 탭의 맨 위가 됩니다'), helperMaxLines: 3),
|
decoration: InputDecoration(labelText: tr('시작 폴더'), helperText: tr('비우면 로그인한 곳 · 예: /volume1/video · 탭의 맨 위가 됩니다'), helperMaxLines: 3),
|
||||||
),
|
),
|
||||||
if (security != 'none') ...[
|
if (security != 'none') ...[
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import '../core/vfs.dart';
|
import '../core/vfs.dart';
|
||||||
import '../l10n/tr.dart';
|
import '../l10n/tr.dart';
|
||||||
|
|
||||||
|
|
@ -25,3 +27,33 @@ String shortPath(String path, {int keep = 3}) {
|
||||||
final parts = friendlyPath(path).split(' › ');
|
final parts = friendlyPath(path).split(' › ');
|
||||||
return parts.length <= keep ? parts.join(' › ') : ['…', ...parts.sublist(parts.length - keep)].join(' › ');
|
return parts.length <= keep ? parts.join(' › ') : ['…', ...parts.sublist(parts.length - keep)].join(' › ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [text] 를 [style] 로 한 줄에 그렸을 때의 폭
|
||||||
|
double textWidth(BuildContext context, String text, TextStyle style) {
|
||||||
|
final tp = TextPainter(
|
||||||
|
text: TextSpan(text: text, style: DefaultTextStyle.of(context).style.merge(style)),
|
||||||
|
textDirection: Directionality.of(context),
|
||||||
|
textScaler: MediaQuery.textScalerOf(context),
|
||||||
|
maxLines: 1)
|
||||||
|
..layout();
|
||||||
|
final w = tp.width;
|
||||||
|
tp.dispose();
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [text] 가 [maxWidth] 를 넘으면 가운데를 "…" 로 줄인다 (앞 · 끝이 보이게 - 412 캡처 10/18, 갈 곳 막대)
|
||||||
|
String middleEllipsis(BuildContext context, String text, TextStyle style, double maxWidth) {
|
||||||
|
if (maxWidth <= 0) return '…';
|
||||||
|
if (textWidth(context, text, style) <= maxWidth) return text;
|
||||||
|
var lo = 0, hi = text.length;
|
||||||
|
String cut(int n) => '${text.substring(0, (n + 1) ~/ 2)}…${text.substring(text.length - n ~/ 2)}';
|
||||||
|
while (lo < hi) {
|
||||||
|
final mid = (lo + hi + 1) ~/ 2;
|
||||||
|
if (textWidth(context, cut(mid), style) <= maxWidth) {
|
||||||
|
lo = mid;
|
||||||
|
} else {
|
||||||
|
hi = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lo == 0 ? '…' : cut(lo);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ Future<SftpServer?> editSftpServer(BuildContext context, AppController c, {SftpS
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 520,
|
width: 520,
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름 (탭에 보임, 비우면 주소)'))),
|
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름'), helperText: tr('탭에 보입니다 · 비우면 주소'), helperMaxLines: 3)),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
|
@ -302,7 +302,7 @@ Future<SftpServer?> editSftpServer(BuildContext context, AppController c, {SftpS
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: root,
|
controller: root,
|
||||||
decoration: InputDecoration(labelText: tr('시작 폴더 (비우면 홈 폴더)'), helperText: tr('예: /volume1/video · 탭의 맨 위가 됩니다'), helperMaxLines: 3),
|
decoration: InputDecoration(labelText: tr('시작 폴더'), helperText: tr('비우면 홈 폴더 · 예: /volume1/video · 탭의 맨 위가 됩니다'), helperMaxLines: 3),
|
||||||
),
|
),
|
||||||
CheckboxListTile(
|
CheckboxListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ Future<SmbServer?> editSmbServer(BuildContext context, AppController c, {SmbServ
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 520,
|
width: 520,
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름 (탭에 보임, 비우면 주소)'))),
|
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름'), helperText: tr('탭에 보입니다 · 비우면 주소'), helperMaxLines: 3)),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
|
@ -211,7 +211,7 @@ Future<SmbServer?> editSmbServer(BuildContext context, AppController c, {SmbServ
|
||||||
decoration: InputDecoration(labelText: tr('공유 이름'), helperText: tr('예: video · home (\\\\서버\\공유 의 공유)'), helperMaxLines: 3),
|
decoration: InputDecoration(labelText: tr('공유 이름'), helperText: tr('예: video · home (\\\\서버\\공유 의 공유)'), helperMaxLines: 3),
|
||||||
onChanged: (_) => set(() {}),
|
onChanged: (_) => set(() {}),
|
||||||
),
|
),
|
||||||
TextField(controller: root, decoration: InputDecoration(labelText: tr('시작 폴더 (공유 안, 비우면 맨 위)'))),
|
TextField(controller: root, decoration: InputDecoration(labelText: tr('시작 폴더'), helperText: tr('공유 안의 폴더 · 비우면 공유의 맨 위'), helperMaxLines: 3)),
|
||||||
TextField(controller: user, decoration: InputDecoration(labelText: tr('아이디 (비우면 게스트)'))),
|
TextField(controller: user, decoration: InputDecoration(labelText: tr('아이디 (비우면 게스트)'))),
|
||||||
TextField(
|
TextField(
|
||||||
controller: pass,
|
controller: pass,
|
||||||
|
|
@ -225,7 +225,7 @@ Future<SmbServer?> editSmbServer(BuildContext context, AppController c, {SmbServ
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextField(controller: domain, decoration: InputDecoration(labelText: tr('도메인 · 작업 그룹 (보통 비움)'))),
|
TextField(controller: domain, decoration: InputDecoration(labelText: tr('도메인 · 작업 그룹'), helperText: tr('보통 비워 둡니다'), helperMaxLines: 3)),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
if (testing) const LinearProgressIndicator(),
|
if (testing) const LinearProgressIndicator(),
|
||||||
if (result != null)
|
if (result != null)
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ Future<DavServer?> editDavServer(BuildContext context, AppController c, {DavServ
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: 520,
|
width: 520,
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름 (탭에 보임, 비우면 주소)'))),
|
TextField(controller: name, decoration: InputDecoration(labelText: tr('이름'), helperText: tr('탭에 보입니다 · 비우면 주소'), helperMaxLines: 3)),
|
||||||
TextField(
|
TextField(
|
||||||
controller: url,
|
controller: url,
|
||||||
keyboardType: TextInputType.url,
|
keyboardType: TextInputType.url,
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ void main() {
|
||||||
..explorerLayout = 'single'
|
..explorerLayout = 'single'
|
||||||
..explorerOnePaneCopy = 'other';
|
..explorerOnePaneCopy = 'other';
|
||||||
await open(tester);
|
await open(tester);
|
||||||
expect(find.textContaining('복사 · 이동 갈 곳'), findsOneWidget);
|
expect(find.textContaining('갈 곳: '), findsOneWidget);
|
||||||
expect(find.textContaining('갈 곳: right'), findsOneWidget, reason: '숨은 창의 폴더 이름 (전체 경로는 풍선 도움말)');
|
expect(find.textContaining('갈 곳: right'), findsOneWidget, reason: '숨은 창의 폴더 이름 (전체 경로는 풍선 도움말)');
|
||||||
await act(tester, () => tester.tap(find.text('doc.txt')));
|
await act(tester, () => tester.tap(find.text('doc.txt')));
|
||||||
await settle(tester, () => false, rounds: 15);
|
await settle(tester, () => false, rounds: 15);
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ void main() {
|
||||||
await act(tester, () => tester.tap(find.text('WebDAV').last));
|
await act(tester, () => tester.tap(find.text('WebDAV').last));
|
||||||
await calm(tester);
|
await calm(tester);
|
||||||
expect(find.text('WebDAV 서버 추가'), findsOneWidget);
|
expect(find.text('WebDAV 서버 추가'), findsOneWidget);
|
||||||
await tester.enterText(find.widgetWithText(TextField, '이름 (탭에 보임, 비우면 주소)'), '집 NAS');
|
await tester.enterText(find.widgetWithText(TextField, '이름'), '집 NAS');
|
||||||
await tester.enterText(find.widgetWithText(TextField, '주소'), server.url);
|
await tester.enterText(find.widgetWithText(TextField, '주소'), server.url);
|
||||||
await tester.enterText(find.widgetWithText(TextField, '아이디'), 'user');
|
await tester.enterText(find.widgetWithText(TextField, '아이디'), 'user');
|
||||||
await tester.enterText(find.widgetWithText(TextField, '비밀번호'), 'pass');
|
await tester.enterText(find.widgetWithText(TextField, '비밀번호'), 'pass');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue