WIP X-plore 비교 40 (관리자 지시 10/20): 파일 탐색기 목록 글자 크기 (80~150%, 처음 100%) · 줄 간격 (좁게 0.8 · 보통 · 넓게 1.25, 처음 보통) - 환경 설정 > 파일 탐색기, 세 스타일 모두, 앱 화면 크기 · 기기 글자 크기와 곱함 (처음 값은 예전 줄 높이 그대로) · 버그 고침: 412 폭 "폴더 + 파일 목록" 의 좁은 트리 (77px) 에서 X-plore · TC 줄이 넘치던 것 (100% 에서도) - 아이콘 칸을 남은 폭만큼 · 시험 (세 스타일 × 100/150 넓게/기기 1.3×120 좁게/80) · 캡처 시험 integration_test/explorer_text_shot_test.dart (검토 대기)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>xplore_view
parent
52b3f7e4d1
commit
ba968cbed9
|
|
@ -543,6 +543,7 @@
|
|||
"{0} 페이지를 지울까요? (저장해야 파일에 반영됩니다)": "Delete page {0}? (Saved to the file only when you save)",
|
||||
"{0} 펼치기": "Expand {0}",
|
||||
"{0} 폴더가 없거나 열 수 없어 내역에서 뺐습니다": "Folder {0} is missing or can't be opened, so it was removed from history",
|
||||
"{0}% (기본)": "{0}% (default)",
|
||||
"{0}% 에서 2분 넘게 나아가지 않아 멈췄습니다. 망이 Tor 를 막고 있거나 느릴 수 있습니다. 잠시 뒤 [다시 시도] 하세요.": "Stopped because it made no progress past {0}% for over 2 minutes. The network may be blocking Tor or be slow. Press [Try again] in a moment.",
|
||||
"{0}. {1} (대기)": "{0}. {1} (waiting)",
|
||||
"{0}: 이 동영상을 {1} 로 옮깁니다": "{0}: moves this video to {1}",
|
||||
|
|
@ -927,6 +928,7 @@
|
|||
"내장 저장소": "Internal storage",
|
||||
"내장 플레이어": "Built-in player",
|
||||
"내장 플레이어로 재생": "Play in built-in player",
|
||||
"넓게": "Wide",
|
||||
"넘기는 방향: 오른쪽 → 왼쪽 (만화)": "Page direction: right → left (manga)",
|
||||
"넘기는 방향: 왼쪽 → 오른쪽": "Page direction: left → right",
|
||||
"넣으면 AES-256 으로 암호화합니다. 비우면 보통 ZIP": "If set, encrypts with AES-256. Leave empty for a normal ZIP",
|
||||
|
|
@ -1257,6 +1259,7 @@
|
|||
"목": "Thu",
|
||||
"목록": "list",
|
||||
"목록 · 영상 옆 · 영상 위에 나오는 광고 영역을 감춥니다": "Hides ad areas in lists · next to · on top of videos",
|
||||
"목록 글자 크기": "List text size",
|
||||
"목록 맨 아래의 [숨긴 항목 보이기] 나 환경 설정 > 파일 탐색기에서 다시 볼 수 있습니다.": "You can see them again with [Show hidden items] at the bottom of the list, or in Settings > File explorer.",
|
||||
"목록 보기": "View list",
|
||||
"목록 파일은 전체 경로로 적어 주세요: {0}": "Please write the full path of the list file: {0}",
|
||||
|
|
@ -1434,6 +1437,7 @@
|
|||
"보조 DNS (비워 둘 수 있음)": "Secondary DNS (may be empty)",
|
||||
"보통": "Normal",
|
||||
"보통 (0.25, 기본)": "Normal (0.25, default)",
|
||||
"보통 (기본)": "Normal (default)",
|
||||
"보통 비워 둡니다": "Usually left empty",
|
||||
"보통: {0}": "Normal: {0}",
|
||||
"복사": "Copy",
|
||||
|
|
@ -2398,6 +2402,7 @@
|
|||
"정해 둠. 저장된 비밀번호 · 설정 · 비밀번호가 필요한 기능을 쓸 때 묻습니다 (앱을 끌 때까지 한 번)": "Set. Asked when using saved passwords, settings or features that need a password (once until the app is closed)",
|
||||
"제목": "Title",
|
||||
"조정 전": "Before",
|
||||
"좁게": "Compact",
|
||||
"좁은 화면에서 동영상 목록이 차지하는 높이 (자동: 목록은 줄 수만큼, 자세히 칸 자리는 남김)": "Height of the video list on narrow screens (Auto: as tall as its rows, keeping room for the details)",
|
||||
"종료": "Quit",
|
||||
"종료 (창 닫기 ✕ · 종료 버튼) 를 누르면": "When you press quit (close window ✕ · quit button)",
|
||||
|
|
@ -2430,6 +2435,7 @@
|
|||
"준비 중": "Preparing",
|
||||
"준비 중…": "Preparing…",
|
||||
"준비하는 중": "Preparing",
|
||||
"줄 간격": "Row spacing",
|
||||
"줄 번호": "Line numbers",
|
||||
"줄 삭제": "Delete line",
|
||||
"중간에서 가로채는 공격일 수 있어 연결하지 않았습니다. 서버 인증서를 바꾼 것이 확실할 때만, 서버 설정의 [믿은 인증서 지우기] 뒤 다시 연결하세요.": "Not connected because this could be an interception attack. Only if you're sure the server certificate was changed, use [Forget trusted certificate] in the server settings and connect again.",
|
||||
|
|
@ -2691,6 +2697,8 @@
|
|||
"파일 탐색기 가운데에 [모니터링] 버튼: 복사 · 이동을 기억해 진행 · 대상 디스크 용량 · 옵션을 보여 주고, 옵션을 고쳐 다시 실행 · 재개하거나 lsync 로 옮깁니다 (복사 · rsync 와 lsync 를 따로).": "[Monitor] button in the middle of the file explorer: remembers copies · moves and shows progress · target disk space · options; change options to run again · resume, or move to lsync (copy · rsync and lsync shown separately).",
|
||||
"파일 탐색기 누르기: 한 번 누르면 선택 → 한 번 누르면 바로 실행. 되돌리기: 환경 설정 > 파일 탐색기 > 누르기": "File explorer tap: single tap selects → single tap opens. To revert: Settings > File explorer > Tap",
|
||||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "File explorer two-pane layout: follow screen shape → side by side. To revert: the [Columns ⇆ / Rows ⇅] button in the file explorer, or Pane layout",
|
||||
"파일 탐색기 목록의 이름 · 크기 글자만. 앱 화면 크기 · 기기 글자 크기와 곱해집니다": "Only the name and size text in the file explorer list. Multiplied by the app screen size and the device text size",
|
||||
"파일 탐색기 목록의 줄 높이": "Row height in the file explorer list",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "You can also change it from the ⋮ menu at the top of the file explorer (side by side · top and bottom · button bar position · buttons)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "File explorer panes: two panes → by screen size (one pane on a portrait phone). To revert: Settings > File explorer > Pane layout",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "File explorer: a single tap now opens a file right away (long-press to select or for the menu). To change: Settings > File explorer > Tap",
|
||||
|
|
|
|||
|
|
@ -543,6 +543,7 @@
|
|||
"{0} 페이지를 지울까요? (저장해야 파일에 반영됩니다)": "{0} ページを削除しますか? (保存するとファイルに反映されます)",
|
||||
"{0} 펼치기": "{0} を展開",
|
||||
"{0} 폴더가 없거나 열 수 없어 내역에서 뺐습니다": "{0} フォルダーが存在しないか開けないため、履歴から削除しました",
|
||||
"{0}% (기본)": "{0}% (既定)",
|
||||
"{0}% 에서 2분 넘게 나아가지 않아 멈췄습니다. 망이 Tor 를 막고 있거나 느릴 수 있습니다. 잠시 뒤 [다시 시도] 하세요.": "{0}% から 2 分以上進まなかったため停止しました。ネットワークが Tor をブロックしているか、遅い可能性があります。少し待ってから [再試行] してください。",
|
||||
"{0}. {1} (대기)": "{0}. {1}(待機)",
|
||||
"{0}: 이 동영상을 {1} 로 옮깁니다": "{0}: この動画を {1} に移動します",
|
||||
|
|
@ -927,6 +928,7 @@
|
|||
"내장 저장소": "内部ストレージ",
|
||||
"내장 플레이어": "内蔵プレーヤー",
|
||||
"내장 플레이어로 재생": "内蔵プレーヤーで再生",
|
||||
"넓게": "広く",
|
||||
"넘기는 방향: 오른쪽 → 왼쪽 (만화)": "めくる方向: 右 → 左 (マンガ)",
|
||||
"넘기는 방향: 왼쪽 → 오른쪽": "めくる方向: 左 → 右",
|
||||
"넣으면 AES-256 으로 암호화합니다. 비우면 보통 ZIP": "入力すると AES-256 で暗号化します。空欄なら通常の ZIP",
|
||||
|
|
@ -1257,6 +1259,7 @@
|
|||
"목": "木",
|
||||
"목록": "一覧",
|
||||
"목록 · 영상 옆 · 영상 위에 나오는 광고 영역을 감춥니다": "リスト・動画の横・動画の上に出る広告エリアを隠します",
|
||||
"목록 글자 크기": "一覧の文字サイズ",
|
||||
"목록 맨 아래의 [숨긴 항목 보이기] 나 환경 설정 > 파일 탐색기에서 다시 볼 수 있습니다.": "リスト最下部の [隠した項目を表示] または 設定 > ファイルエクスプローラー で再び表示できます。",
|
||||
"목록 보기": "リストを見る",
|
||||
"목록 파일은 전체 경로로 적어 주세요: {0}": "リストファイルはフルパスで書いてください: {0}",
|
||||
|
|
@ -1434,6 +1437,7 @@
|
|||
"보조 DNS (비워 둘 수 있음)": "代替 DNS (空欄可)",
|
||||
"보통": "普通",
|
||||
"보통 (0.25, 기본)": "普通 (0.25、既定)",
|
||||
"보통 (기본)": "標準 (既定)",
|
||||
"보통 비워 둡니다": "通常は空欄",
|
||||
"보통: {0}": "普通: {0}",
|
||||
"복사": "コピー",
|
||||
|
|
@ -2398,6 +2402,7 @@
|
|||
"정해 둠. 저장된 비밀번호 · 설정 · 비밀번호가 필요한 기능을 쓸 때 묻습니다 (앱을 끌 때까지 한 번)": "設定済み。保存したパスワード・設定・パスワードが必要な機能を使うときに尋ねます (アプリを終了するまで 1 回)",
|
||||
"제목": "タイトル",
|
||||
"조정 전": "調整前",
|
||||
"좁게": "狭く",
|
||||
"좁은 화면에서 동영상 목록이 차지하는 높이 (자동: 목록은 줄 수만큼, 자세히 칸 자리는 남김)": "狭い画面で動画リストが占める高さ (自動: 行の数だけ、詳細欄の場所は残す)",
|
||||
"종료": "終了",
|
||||
"종료 (창 닫기 ✕ · 종료 버튼) 를 누르면": "終了(ウィンドウを閉じる ✕・終了ボタン)を押したとき",
|
||||
|
|
@ -2430,6 +2435,7 @@
|
|||
"준비 중": "準備中",
|
||||
"준비 중…": "準備中…",
|
||||
"준비하는 중": "準備中",
|
||||
"줄 간격": "行の間隔",
|
||||
"줄 번호": "行番号",
|
||||
"줄 삭제": "行を削除",
|
||||
"중간에서 가로채는 공격일 수 있어 연결하지 않았습니다. 서버 인증서를 바꾼 것이 확실할 때만, 서버 설정의 [믿은 인증서 지우기] 뒤 다시 연결하세요.": "中間者攻撃の可能性があるため接続しませんでした。サーバー証明書を変えたことが確かな場合だけ、サーバー設定の [信頼した証明書を削除] の後に再接続してください。",
|
||||
|
|
@ -2691,6 +2697,8 @@
|
|||
"파일 탐색기 가운데에 [모니터링] 버튼: 복사 · 이동을 기억해 진행 · 대상 디스크 용량 · 옵션을 보여 주고, 옵션을 고쳐 다시 실행 · 재개하거나 lsync 로 옮깁니다 (복사 · rsync 와 lsync 를 따로).": "ファイルエクスプローラー中央に [モニタリング] ボタン: コピー · 移動を記憶して進捗 · 対象ディスク容量 · オプションを表示し、オプションを変えて再実行 · 再開、または lsync へ移動します (コピー · rsync と lsync は別々)。",
|
||||
"파일 탐색기 누르기: 한 번 누르면 선택 → 한 번 누르면 바로 실행. 되돌리기: 환경 설정 > 파일 탐색기 > 누르기": "ファイルエクスプローラーのタップ: 1 回で選択 → 1 回ですぐ開く。元に戻す: 環境設定 > ファイルエクスプローラー > タップ",
|
||||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "ファイルエクスプローラーの 2 画面配置: 画面の形に合わせる → 左右。元に戻す: ファイルエクスプローラーの [左右 ⇆ / 上下 ⇅] ボタンまたは画面配置",
|
||||
"파일 탐색기 목록의 이름 · 크기 글자만. 앱 화면 크기 · 기기 글자 크기와 곱해집니다": "ファイルエクスプローラー一覧の名前・サイズの文字のみ。アプリの画面サイズ・端末の文字サイズと掛け合わされます",
|
||||
"파일 탐색기 목록의 줄 높이": "ファイルエクスプローラー一覧の行の高さ",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "ファイルエクスプローラー上部の ⋮ メニューからも変えられます (左右 · 上下 · ボタン列の位置 · ボタン構成)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "ファイルエクスプローラーの画面: 2 画面 → 画面サイズに合わせる (縦向きのスマホは 1 画面)。元に戻す: 環境設定 > ファイルエクスプローラー > 画面配置",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "ファイルエクスプローラー: ファイルを 1 回タップするとすぐ開きます (選択 · メニューは長押し)。変更: 環境設定 > ファイルエクスプローラー > タップ",
|
||||
|
|
|
|||
|
|
@ -543,6 +543,7 @@
|
|||
"{0} 페이지를 지울까요? (저장해야 파일에 반영됩니다)": "删除第 {0} 页? (保存后才会写入文件)",
|
||||
"{0} 펼치기": "展开 {0}",
|
||||
"{0} 폴더가 없거나 열 수 없어 내역에서 뺐습니다": "文件夹 {0} 不存在或无法打开,已从历史记录中移除",
|
||||
"{0}% (기본)": "{0}% (默认)",
|
||||
"{0}% 에서 2분 넘게 나아가지 않아 멈췄습니다. 망이 Tor 를 막고 있거나 느릴 수 있습니다. 잠시 뒤 [다시 시도] 하세요.": "在 {0}% 停滞超过 2 分钟,已停止。网络可能在阻止 Tor 或速度较慢。请稍后点 [重试]。",
|
||||
"{0}. {1} (대기)": "{0}. {1}(等待)",
|
||||
"{0}: 이 동영상을 {1} 로 옮깁니다": "{0}: 将此视频移到 {1}",
|
||||
|
|
@ -927,6 +928,7 @@
|
|||
"내장 저장소": "内部存储",
|
||||
"내장 플레이어": "内置播放器",
|
||||
"내장 플레이어로 재생": "用内置播放器播放",
|
||||
"넓게": "宽松",
|
||||
"넘기는 방향: 오른쪽 → 왼쪽 (만화)": "翻页方向: 右 → 左 (漫画)",
|
||||
"넘기는 방향: 왼쪽 → 오른쪽": "翻页方向: 左 → 右",
|
||||
"넣으면 AES-256 으로 암호화합니다. 비우면 보통 ZIP": "填写后使用 AES-256 加密。留空则为普通 ZIP",
|
||||
|
|
@ -1257,6 +1259,7 @@
|
|||
"목": "四",
|
||||
"목록": "列表",
|
||||
"목록 · 영상 옆 · 영상 위에 나오는 광고 영역을 감춥니다": "隐藏列表 · 视频旁 · 视频上方出现的广告区域",
|
||||
"목록 글자 크기": "列表文字大小",
|
||||
"목록 맨 아래의 [숨긴 항목 보이기] 나 환경 설정 > 파일 탐색기에서 다시 볼 수 있습니다.": "可通过列表底部的 [显示隐藏项] 或 设置 > 文件管理器 重新查看。",
|
||||
"목록 보기": "查看列表",
|
||||
"목록 파일은 전체 경로로 적어 주세요: {0}": "请填写列表文件的完整路径: {0}",
|
||||
|
|
@ -1434,6 +1437,7 @@
|
|||
"보조 DNS (비워 둘 수 있음)": "备用 DNS (可留空)",
|
||||
"보통": "普通",
|
||||
"보통 (0.25, 기본)": "普通 (0.25,默认)",
|
||||
"보통 (기본)": "正常 (默认)",
|
||||
"보통 비워 둡니다": "通常留空",
|
||||
"보통: {0}": "普通:{0}",
|
||||
"복사": "复制",
|
||||
|
|
@ -2398,6 +2402,7 @@
|
|||
"정해 둠. 저장된 비밀번호 · 설정 · 비밀번호가 필요한 기능을 쓸 때 묻습니다 (앱을 끌 때까지 한 번)": "已设置。使用已保存的密码 · 设置 · 需要密码的功能时询问 (在关闭应用前只问一次)",
|
||||
"제목": "标题",
|
||||
"조정 전": "调整前",
|
||||
"좁게": "紧凑",
|
||||
"좁은 화면에서 동영상 목록이 차지하는 높이 (자동: 목록은 줄 수만큼, 자세히 칸 자리는 남김)": "窄屏时视频列表所占高度 (自动: 按行数,并为详情区留出空间)",
|
||||
"종료": "退出",
|
||||
"종료 (창 닫기 ✕ · 종료 버튼) 를 누르면": "点击退出(关闭窗口 ✕ · 退出按钮)时",
|
||||
|
|
@ -2430,6 +2435,7 @@
|
|||
"준비 중": "准备中",
|
||||
"준비 중…": "准备中…",
|
||||
"준비하는 중": "正在准备",
|
||||
"줄 간격": "行间距",
|
||||
"줄 번호": "行号",
|
||||
"줄 삭제": "删除行",
|
||||
"중간에서 가로채는 공격일 수 있어 연결하지 않았습니다. 서버 인증서를 바꾼 것이 확실할 때만, 서버 설정의 [믿은 인증서 지우기] 뒤 다시 연결하세요.": "可能是中间人攻击,因此未连接。仅当确定服务器证书已更换时,在服务器设置中 [删除已信任的证书] 后重新连接。",
|
||||
|
|
@ -2691,6 +2697,8 @@
|
|||
"파일 탐색기 가운데에 [모니터링] 버튼: 복사 · 이동을 기억해 진행 · 대상 디스크 용량 · 옵션을 보여 주고, 옵션을 고쳐 다시 실행 · 재개하거나 lsync 로 옮깁니다 (복사 · rsync 와 lsync 를 따로).": "文件浏览器中间的 [监控] 按钮: 记住复制 · 移动并显示进度 · 目标磁盘容量 · 选项,可修改选项后重新运行 · 继续,或移到 lsync (复制 · rsync 与 lsync 分开显示)。",
|
||||
"파일 탐색기 누르기: 한 번 누르면 선택 → 한 번 누르면 바로 실행. 되돌리기: 환경 설정 > 파일 탐색기 > 누르기": "文件浏览器点击: 单击选择 → 单击直接打开。恢复: 设置 > 文件浏览器 > 点击",
|
||||
"파일 탐색기 두 창 배치: 화면 모양 따라 → 좌우. 되돌리기: 파일 탐색기의 [좌우 ⇆ / 위아래 ⇅] 버튼 또는 창 배치": "文件浏览器双窗格布局: 跟随屏幕形状 → 左右。恢复: 文件浏览器中的 [左右 ⇆ / 上下 ⇅] 按钮或窗格布局",
|
||||
"파일 탐색기 목록의 이름 · 크기 글자만. 앱 화면 크기 · 기기 글자 크기와 곱해집니다": "仅文件管理器列表中的名称和大小文字。会与应用界面大小及设备文字大小相乘",
|
||||
"파일 탐색기 목록의 줄 높이": "文件管理器列表的行高",
|
||||
"파일 탐색기 위쪽 ⋮ 메뉴에서도 바꿀 수 있습니다 (좌우 · 위아래 · 버튼 줄 위치 · 버튼 구성)": "也可以在文件浏览器顶部的 ⋮ 菜单中更改 (左右 · 上下 · 按钮栏位置 · 按钮配置)",
|
||||
"파일 탐색기 창: 두 창 → 화면 크기 따라 (폰 세로는 한 창). 되돌리기: 환경 설정 > 파일 탐색기 > 창 배치": "文件浏览器窗格: 双窗格 → 按屏幕大小 (竖屏手机为单窗格)。恢复: 设置 > 文件浏览器 > 窗格布局",
|
||||
"파일 탐색기: 파일을 한 번 누르면 바로 엽니다 (고르기 · 메뉴는 길게 누르기). 바꾸기: 환경 설정 > 파일 탐색기 > 누르기": "文件浏览器:单击文件会立即打开(选择 · 菜单请长按)。更改:设置 > 文件浏览器 > 点按",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
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/services/platform_services.dart';
|
||||
import 'package:jj_mkvmaker/ui/explorer_page.dart';
|
||||
import 'package:jj_mkvmaker/ui/theme.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
/// X-plore 비교 40 (관리자 지시 10/20): 412 폭 · 목록 글자 150% · 넓게 (그리고 처음 값) 를 실제 글꼴로 그려 PNG 로 (JJ_SHOT_DIR).
|
||||
/// 세 스타일 모두. 넘치면 (RenderFlex overflow) 시험이 실패한다
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
testWidgets('40: 목록 글자 크기 · 줄 간격 화면 그림 (412 폭)', (tester) async {
|
||||
final out = Platform.environment['JJ_SHOT_DIR'] ?? Directory.systemTemp.path;
|
||||
final tmp = Directory.systemTemp.createTempSync('jj_textshot_');
|
||||
addTearDown(() => tmp.deleteSync(recursive: true));
|
||||
File(p.join(tmp.path, '아주 긴 이름의 동영상 파일 - 글자 크기 시험용 2026 최종본.mp4')).writeAsStringSync('v' * 123456);
|
||||
File(p.join(tmp.path, 'Very long English file name for the text size check.txt')).writeAsStringSync('t' * 4321);
|
||||
File(p.join(tmp.path, 'a.jpg')).writeAsStringSync('x');
|
||||
Directory(p.join(tmp.path, '폴더 하나')).createSync();
|
||||
Directory(p.join(tmp.path, 'Another folder with a long name')).createSync();
|
||||
final c = AppController(PlatformServices.create());
|
||||
c.settings.explorerPaths = [tmp.path, tmp.path];
|
||||
final key = GlobalKey();
|
||||
for (final layout in ['single', 'split']) {
|
||||
for (final style in ['xplore', 'windows', 'totalcmd']) {
|
||||
for (final (scale, spacing) in [(100, 'normal'), (150, 'wide'), (80, 'compact')]) {
|
||||
c.settings
|
||||
..explorerLayout = layout
|
||||
..explorerStyle = style
|
||||
..explorerTextScale = scale
|
||||
..explorerRowSpacing = spacing;
|
||||
tester.view.physicalSize = const Size(412, 900);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
await tester.runAsync(() => tester.pumpWidget(MaterialApp(
|
||||
theme: buildTheme(),
|
||||
home: RepaintBoundary(key: key, child: ExplorerPage(c: c)),
|
||||
)));
|
||||
for (var i = 0; i < 12; i++) {
|
||||
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 250)));
|
||||
await tester.pump();
|
||||
}
|
||||
expect(tester.takeException(), isNull, reason: '$layout $style $scale% $spacing 넘치지 않음');
|
||||
final boundary = key.currentContext!.findRenderObject()! as RenderRepaintBoundary;
|
||||
final image = await tester.runAsync(() => boundary.toImage());
|
||||
final bytes = await tester.runAsync(() => image!.toByteData(format: ui.ImageByteFormat.png));
|
||||
File('$out/explorer_text_${layout}_${style}_${scale}_$spacing.png').writeAsBytesSync(bytes!.buffer.asUint8List());
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 300)));
|
||||
}
|
||||
}
|
||||
}
|
||||
tester.view.reset();
|
||||
});
|
||||
}
|
||||
|
|
@ -418,6 +418,14 @@ class AppSettings {
|
|||
/// 다시 · 두 번 눌러도 아래 줄이 움직이지 않게) 와 부딪혀 설정으로만. 켜도 두 번 누르기의 두 번째는 접지 않는다
|
||||
bool explorerRetapCollapse = false;
|
||||
|
||||
/// X-plore 비교 40 (관리자 지시 10/20): 파일 탐색기 목록만의 글자 크기 (%, 80~150, 처음 100 = 지금 그대로).
|
||||
/// 앱 화면 크기 · 기기 글자 크기와 곱해진다
|
||||
int explorerTextScale = 100;
|
||||
static const explorerTextScaleMin = 80, explorerTextScaleMax = 150;
|
||||
|
||||
/// X-plore 비교 40: 목록 줄 간격 'compact' 좁게 · 'normal' 보통 (처음 값 = 지금 그대로) · 'wide' 넓게
|
||||
String explorerRowSpacing = 'normal';
|
||||
|
||||
/// X-plore 비교 i: 일괄 이름 바꾸기의 마지막 규칙 (다음에 창이 그 값으로 열림, 비면 처음 값)
|
||||
Map<String, dynamic> batchRenameLast = {};
|
||||
|
||||
|
|
@ -832,6 +840,8 @@ class AppSettings {
|
|||
'explorerLayout': explorerLayout,
|
||||
'explorerOnePaneCopy': explorerOnePaneCopy,
|
||||
'explorerRetapCollapse': explorerRetapCollapse,
|
||||
'explorerTextScale': explorerTextScale,
|
||||
'explorerRowSpacing': explorerRowSpacing,
|
||||
'batchRenameLast': batchRenameLast,
|
||||
'explorerRootsInTree': explorerRootsInTree,
|
||||
'explorerAlwaysMarks': explorerAlwaysMarks,
|
||||
|
|
@ -1063,6 +1073,11 @@ class AppSettings {
|
|||
// 'auto' = 넓은 화면은 두 창, 좁은 화면 (폰 세로) 은 한 창. 예전 기본 'dual' 은 한 번 'auto' 로
|
||||
..explorerOnePaneCopy = j['explorerOnePaneCopy'] == 'other' ? 'other' : 'clip'
|
||||
..explorerRetapCollapse = j['explorerRetapCollapse'] == true
|
||||
// 값이 없거나 틀리면 지금 그대로 (100% · 보통), 범위 밖은 끝으로
|
||||
..explorerTextScale = j['explorerTextScale'] is num
|
||||
? (j['explorerTextScale'] as num).round().clamp(explorerTextScaleMin, explorerTextScaleMax)
|
||||
: 100
|
||||
..explorerRowSpacing = const {'compact', 'normal', 'wide'}.contains(j['explorerRowSpacing']) ? j['explorerRowSpacing'] as String : 'normal'
|
||||
..batchRenameLast = j['batchRenameLast'] is Map ? Map<String, dynamic>.from(j['batchRenameLast'] as Map) : {}
|
||||
..explorerRootsInTree = j['explorerRootsInTree'] != false
|
||||
..explorerAlwaysMarks = j['explorerAlwaysMarks'] != false
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ enum ExplorerStyle {
|
|||
|
||||
double get rowHeight => switch (this) { xplore => 52, windows => 34, totalcmd => 26 };
|
||||
|
||||
/// 253: 줄 높이 - 기기 글자 크기를 키우면 그만큼 (고정 높이라 1.6배에서 이름 · 크기 두 줄이 넘쳤다)
|
||||
double rowHeightOf(BuildContext context) {
|
||||
final s = MediaQuery.textScalerOf(context).scale(fontSize) / fontSize;
|
||||
return s <= 1 ? rowHeight : (rowHeight * s).roundToDouble();
|
||||
/// 253: 줄 높이 - 기기 글자 크기를 키우면 그만큼 (고정 높이라 1.6배에서 이름 · 크기 두 줄이 넘쳤다).
|
||||
/// X-plore 비교 40: [textScale] 목록 글자 크기 (기기 글자 크기와 곱함) · [spacing] 줄 간격 ([rowSpacingFactor])
|
||||
double rowHeightOf(BuildContext context, {double textScale = 1, double spacing = 1}) {
|
||||
final s = MediaQuery.textScalerOf(context).scale(fontSize) * textScale / fontSize;
|
||||
return ((s <= 1 ? rowHeight : rowHeight * s) * spacing).roundToDouble();
|
||||
}
|
||||
double get iconSize => switch (this) { xplore => 30, windows => 20, totalcmd => 16 };
|
||||
double get indent => switch (this) { xplore => 16, windows => 14, totalcmd => 12 };
|
||||
|
|
@ -48,6 +49,35 @@ const _sheets = {'xls', 'xlsx', 'ods'};
|
|||
const _slides = {'ppt', 'pptx', 'odp'};
|
||||
const _programs = {'exe', 'msi', 'bat', 'cmd', 'ps1', 'apk'};
|
||||
|
||||
/// X-plore 비교 40: 줄 간격 설정 → 줄 높이 배수 (좁게 · 보통 (지금 그대로) · 넓게)
|
||||
double rowSpacingFactor(String spacing) => switch (spacing) { 'compact' => 0.8, 'wide' => 1.25, _ => 1.0 };
|
||||
|
||||
/// X-plore 비교 40: 목록 글자만 [factor] 배 (앱 화면 크기 · 기기 글자 크기에 곱함). 1 이면 그대로
|
||||
Widget scaleListText(BuildContext context, double factor, Widget child) {
|
||||
if (factor == 1) return child;
|
||||
final mq = MediaQuery.of(context);
|
||||
return MediaQuery(data: mq.copyWith(textScaler: _TimesScaler(mq.textScaler, factor)), child: child);
|
||||
}
|
||||
|
||||
class _TimesScaler extends TextScaler {
|
||||
final TextScaler base;
|
||||
final double factor;
|
||||
const _TimesScaler(this.base, this.factor);
|
||||
|
||||
@override
|
||||
double scale(double fontSize) => base.scale(fontSize) * factor;
|
||||
|
||||
// ignore: deprecated_member_use
|
||||
@override
|
||||
double get textScaleFactor => base.scale(14) / 14 * factor;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is _TimesScaler && other.base == base && other.factor == factor;
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(base, factor);
|
||||
}
|
||||
|
||||
/// 파일 종류별 아이콘 · 색 (스타일마다 다르게)
|
||||
(IconData, Color) fileIcon(ExplorerStyle style, FileEntry e, {bool open = false}) {
|
||||
final x = e.ext;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
|
||||
|
|
@ -1076,7 +1077,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
final pos = pane.scroll.position;
|
||||
// 180: 끝 (maxScrollExtent) 으로 자르지 않는다 - 줄이 막 늘어난 때는 끝이 아직 앞의 것이라 보던 폴더로 못 간다.
|
||||
// 넘치면 다음 배치 때 실제 끝으로 맞춰진다
|
||||
pane.scroll.jumpTo((i * _look.rowHeightOf(context) - pos.viewportDimension / 4).clamp(0.0, double.infinity));
|
||||
pane.scroll.jumpTo((i * _rowH() - pos.viewportDimension / 4).clamp(0.0, double.infinity));
|
||||
}
|
||||
|
||||
/// 28 확인 (10/20): 창의 목록이 화면에 새로 붙으면 (좁은 Rsync 화면의 [오른쪽] 탭을 처음 볼 때 · 폭이 바뀌어 두 창이 될 때)
|
||||
|
|
@ -1145,6 +1146,10 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
/// 지금 모양 (환경 설정 > 파일 탐색기 > 스타일)
|
||||
ExplorerStyle get _look => ExplorerStyle.of(c.settings.explorerStyle);
|
||||
|
||||
/// X-plore 비교 40: 목록 글자 크기 (설정 %) · 줄 간격을 넣은 줄 높이
|
||||
double get _listTextScale => c.settings.explorerTextScale / 100;
|
||||
double _rowH() => _look.rowHeightOf(context, textScale: _listTextScale, spacing: rowSpacingFactor(c.settings.explorerRowSpacing));
|
||||
|
||||
/// 왼쪽 폴더 트리 + 오른쪽 파일 목록 배치
|
||||
bool get _split => !widget.rsync && c.settings.explorerLayout == 'split';
|
||||
|
||||
|
|
@ -4916,16 +4921,16 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
),
|
||||
Expanded(
|
||||
child: Stack(children: [
|
||||
ListView.builder(
|
||||
scaleListText(context, _listTextScale, ListView.builder(
|
||||
controller: pane.scroll,
|
||||
itemCount: rows.length,
|
||||
itemExtent: look.rowHeightOf(context),
|
||||
itemExtent: _rowH(),
|
||||
// 76: 줄 위젯은 항목을 따라간다 (아래 [_rowKey])
|
||||
itemBuilder: (_, k) => KeyedSubtree(
|
||||
key: _rowKey(rows[k]),
|
||||
child: rows[k].kind != 0 ? _extraRow(pane, rows[k]) : _rowView(pane, rows[k], compact: foldersOnly)),
|
||||
findChildIndexCallback: _rowIndexOf(rows),
|
||||
),
|
||||
)),
|
||||
// 읽는 중 (WebDAV 서버를 기다릴 때 등). 180: 목록 위에 겹쳐 그린다 (끼어들면 목록이 밀려 다음 것을 누르려다 엉뚱한 것을 누른다)
|
||||
if (pane.loading.isNotEmpty) const Positioned(left: 0, right: 0, top: 0, child: LinearProgressIndicator(minHeight: 2)),
|
||||
]),
|
||||
|
|
@ -4985,14 +4990,14 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
? const Center(child: CircularProgressIndicator())
|
||||
: entries.isEmpty && !up
|
||||
? Center(child: Text(tr('비어 있음'), style: const TextStyle(color: JjColors.textDim)))
|
||||
: ListView.builder(
|
||||
: scaleListText(context, _listTextScale, ListView.builder(
|
||||
controller: pane.listScroll,
|
||||
itemCount: rows.length,
|
||||
itemExtent: look.rowHeightOf(context),
|
||||
itemExtent: _rowH(),
|
||||
itemBuilder: (_, k) => KeyedSubtree(
|
||||
key: _rowKey(rows[k]), child: rows[k].kind != 0 ? _extraRow(pane, rows[k]) : _rowView(pane, rows[k], list: true)),
|
||||
findChildIndexCallback: _rowIndexOf(rows),
|
||||
),
|
||||
)),
|
||||
),
|
||||
if (_selecting) _marksBar(pane, listDir: dir),
|
||||
]));
|
||||
|
|
@ -5495,7 +5500,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
// 손가락으로 누르는 기기 (Android) 는 폭도 넓게
|
||||
Widget chevron() => SizedBox(
|
||||
width: chevronWidth,
|
||||
height: look.rowHeightOf(context),
|
||||
height: _rowH(),
|
||||
child: (e.isDir || _canBrowseArchive(e)) && !list && !row.isUp
|
||||
? (loading
|
||||
? const Center(
|
||||
|
|
@ -5521,15 +5526,19 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
Widget nameCell() => LayoutBuilder(builder: (context, box) {
|
||||
final fixed = (list ? 0 : chevronWidth) + (look.rich ? 64 : look.iconSize + 12) + 48.0;
|
||||
final indent = list ? 0.0 : (row.depth * look.indent).clamp(0.0, (box.maxWidth - fixed).clamp(0.0, double.infinity));
|
||||
// 아주 좁은 창 (412 폭 "폴더 + 파일 목록" 의 트리, 77px 쯤): 아이콘 칸 · 틈을 남은 폭만큼만 (아이콘은 줄여 그림) - 넘치지 않게
|
||||
final room = (box.maxWidth - indent - (list ? 0 : chevronWidth)).clamp(0.0, double.infinity);
|
||||
final iconW = math.min(look.rich ? 56.0 : look.iconSize + 6, room);
|
||||
final gapW = math.min(look.rich ? 8.0 : 6.0, room - iconW);
|
||||
return Row(children: [
|
||||
SizedBox(width: indent),
|
||||
if (!list) chevron(),
|
||||
SizedBox(
|
||||
width: look.rich ? 56 : look.iconSize + 6,
|
||||
height: look.rowHeightOf(context) - 8,
|
||||
child: Center(child: _icon(e, row.isRoot, open, up: row.isUp)),
|
||||
width: iconW,
|
||||
height: _rowH() - 8,
|
||||
child: Center(child: FittedBox(fit: BoxFit.scaleDown, child: _icon(e, row.isRoot, open, up: row.isUp))),
|
||||
),
|
||||
SizedBox(width: look.rich ? 8 : 6),
|
||||
SizedBox(width: gapW),
|
||||
Expanded(
|
||||
child: look.rich && !e.isDir && !row.isUp
|
||||
? Column(
|
||||
|
|
|
|||
|
|
@ -896,6 +896,34 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||
value: s.explorerRetapCollapse,
|
||||
onChanged: (v) => c.updateSettings((x) => x.explorerRetapCollapse = v),
|
||||
),
|
||||
// X-plore 비교 40 (관리자 지시 10/20): 목록만의 글자 크기 · 줄 간격 (세 스타일 모두, 앱 화면 크기 · 기기 글자 크기와 곱함)
|
||||
SettingTile(
|
||||
title: Text(tr('목록 글자 크기')),
|
||||
subtitle: Text(tr('파일 탐색기 목록의 이름 · 크기 글자만. 앱 화면 크기 · 기기 글자 크기와 곱해집니다')),
|
||||
trailing: DropdownButton<int>(
|
||||
value: s.explorerTextScale,
|
||||
items: [
|
||||
for (var v = AppSettings.explorerTextScaleMin; v <= AppSettings.explorerTextScaleMax; v += 10)
|
||||
DropdownMenuItem(value: v, child: Text(v == 100 ? trf('{0}% (기본)', [v]) : '$v%')),
|
||||
if (s.explorerTextScale % 10 != 0)
|
||||
DropdownMenuItem(value: s.explorerTextScale, child: Text('${s.explorerTextScale}%')),
|
||||
],
|
||||
onChanged: (v) => c.updateSettings((x) => x.explorerTextScale = v!),
|
||||
),
|
||||
),
|
||||
SettingTile(
|
||||
title: Text(tr('줄 간격')),
|
||||
subtitle: Text(tr('파일 탐색기 목록의 줄 높이')),
|
||||
trailing: DropdownButton<String>(
|
||||
value: s.explorerRowSpacing,
|
||||
items: [
|
||||
DropdownMenuItem(value: 'compact', child: Text(tr('좁게'))),
|
||||
DropdownMenuItem(value: 'normal', child: Text(tr('보통 (기본)'))),
|
||||
DropdownMenuItem(value: 'wide', child: Text(tr('넓게'))),
|
||||
],
|
||||
onChanged: (v) => c.updateSettings((x) => x.explorerRowSpacing = v!),
|
||||
),
|
||||
),
|
||||
// X-plore 숨기기: 목록에서 숨긴 것 보기 · 풀기 (관리자 결정 10/18)
|
||||
ListTile(
|
||||
title: Text(trf('목록에서 숨긴 항목 ({0}개)', [s.explorerHiddenItems.length])),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jj_mkvmaker/app/app_controller.dart';
|
||||
import 'package:jj_mkvmaker/app/settings.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/explorer_page.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
/// X-plore 비교 40 (관리자 지시 10/20): 파일 탐색기 목록만의 글자 크기 (80~150%) · 줄 간격 (좁게 · 보통 · 넓게)
|
||||
void main() {
|
||||
late Directory tmp;
|
||||
setUp(() => tmp = Directory.systemTemp.createTempSync('jj_textscale_'));
|
||||
tearDown(() => tmp.deleteSync(recursive: true));
|
||||
|
||||
test('설정: 처음은 100% · 보통 (지금 그대로), 저장 · 읽기, 틀린 값은 그대로 쪽으로 · 범위 밖은 끝으로', () {
|
||||
final s = AppSettings();
|
||||
expect((s.explorerTextScale, s.explorerRowSpacing), (100, 'normal'));
|
||||
s
|
||||
..explorerTextScale = 130
|
||||
..explorerRowSpacing = 'wide';
|
||||
final back = AppSettings.fromJson(s.toJson());
|
||||
expect((back.explorerTextScale, back.explorerRowSpacing), (130, 'wide'));
|
||||
expect(AppSettings.fromJson({}).explorerTextScale, 100);
|
||||
expect(AppSettings.fromJson({'explorerTextScale': 'x', 'explorerRowSpacing': 'huge'}).explorerRowSpacing, 'normal');
|
||||
expect(AppSettings.fromJson({'explorerTextScale': 300}).explorerTextScale, 150);
|
||||
expect(AppSettings.fromJson({'explorerTextScale': 10}).explorerTextScale, 80);
|
||||
});
|
||||
|
||||
/// [name] 글자의 실제 글자 크기 (기기 · 목록 글자 크기를 곱한 것)
|
||||
double shownSize(WidgetTester tester, String name) {
|
||||
final para = tester.renderObject<RenderParagraph>(find.text(name).last);
|
||||
final size = para.text.style?.fontSize ?? 14;
|
||||
return para.textScaler.scale(size);
|
||||
}
|
||||
|
||||
/// 이름 줄 높이
|
||||
double rowHeight(WidgetTester tester, String name) =>
|
||||
tester.getSize(find.ancestor(of: find.text(name).last, matching: find.byType(KeyedSubtree)).first).height;
|
||||
|
||||
Future<AppController> open(WidgetTester tester, String style, String wait,
|
||||
{double device = 1, int scale = 100, String spacing = 'normal'}) async {
|
||||
const pp = MethodChannel('plugins.flutter.io/path_provider');
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(pp, (_) async => tmp.path);
|
||||
addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(pp, null));
|
||||
File(p.join(tmp.path, '아주 긴 이름의 동영상 파일 - 글자 크기 시험용 2026 최종본.mp4')).writeAsStringSync('v' * 2000);
|
||||
File(p.join(tmp.path, 'a.txt')).writeAsStringSync('a');
|
||||
Directory(p.join(tmp.path, 'sub')).createSync();
|
||||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||||
c.settings
|
||||
..explorerPaths = [tmp.path, tmp.path]
|
||||
// 폴더 + 파일 목록: 오른쪽 목록은 그 폴더의 것만이라 짧다 (트리는 Temp 의 다른 폴더가 많아 아래로 밀린다)
|
||||
..explorerLayout = 'split'
|
||||
..explorerStyle = style
|
||||
..explorerTextScale = scale
|
||||
..explorerRowSpacing = spacing;
|
||||
await tester.runAsync(() => tester.pumpWidget(MaterialApp(
|
||||
builder: (ctx, child) => MediaQuery(data: MediaQuery.of(ctx).copyWith(textScaler: TextScaler.linear(device)), child: child!),
|
||||
home: ExplorerPage(c: c))));
|
||||
// 목록을 다 읽을 때까지 (다른 시험과 함께 돌면 느리다 - 10초까지)
|
||||
for (var i = 0; i < 200 && (i < 15 || find.text(wait).evaluate().isEmpty); i++) {
|
||||
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 50)));
|
||||
await tester.pump();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
Future<void> close(WidgetTester tester) async {
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
}
|
||||
|
||||
for (final style in ['xplore', 'windows', 'totalcmd']) {
|
||||
final a = style == 'totalcmd' ? 'a' : 'a.txt';
|
||||
testWidgets('40: $style - 처음 값 (100% · 보통) 은 지금 그대로 · 150% · 넓게는 글자 1.5배 · 줄 높이 늘어남 · 412 폭에서 넘치지 않음', (tester) async {
|
||||
tester.view.physicalSize = const Size(412, 900);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
await open(tester, style, a);
|
||||
expect(tester.takeException(), isNull);
|
||||
final base = shownSize(tester, a), baseH = rowHeight(tester, a);
|
||||
expect(baseH, {'xplore': 52.0, 'windows': 34.0, 'totalcmd': 26.0}[style], reason: '처음 값은 예전 줄 높이 그대로');
|
||||
await close(tester);
|
||||
|
||||
await open(tester, style, a, scale: 150, spacing: 'wide');
|
||||
expect(tester.takeException(), isNull, reason: '412 폭 · 150% · 넓게에서 넘치지 않는다');
|
||||
expect(shownSize(tester, a), closeTo(base * 1.5, 0.01));
|
||||
expect(rowHeight(tester, a), (baseH * 1.5 * 1.25).roundToDouble());
|
||||
await close(tester);
|
||||
|
||||
// 기기 글자 크기 1.3 과 곱해진다 · 좁게
|
||||
await open(tester, style, a, device: 1.3, scale: 120, spacing: 'compact');
|
||||
expect(tester.takeException(), isNull);
|
||||
expect(shownSize(tester, a), closeTo(base * 1.3 * 1.2, 0.01));
|
||||
expect(rowHeight(tester, a), (baseH * 1.3 * 1.2 * 0.8).roundToDouble());
|
||||
await close(tester);
|
||||
|
||||
// 80% 는 글자만 작게 (줄은 예전 높이 - 누르기 크기를 줄이지 않음)
|
||||
await open(tester, style, a, scale: 80);
|
||||
expect(shownSize(tester, a), closeTo(base * 0.8, 0.01));
|
||||
expect(rowHeight(tester, a), baseH);
|
||||
await close(tester);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue