Rsync 확인 창: 1280×720 에서 체크 · 경고가 버튼에 가리지 않게
- 미리 보기 높이를 화면 높이의 28% (140 이상) 로 - [원본 파일 지우기] 체크 · 경고를 미리 보기 위로 - 시험: 1280×720 에서 체크 · 경고가 버튼보다 위 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>fix_mkv
parent
4f10cf167f
commit
d6f3de130c
|
|
@ -2057,6 +2057,40 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
if (nested)
|
||||
Text(tr('원본이 대상 폴더 안에 있습니다: 원본의 내용이 대상 폴더 바로 아래에 복사됩니다 (원본 폴더는 그대로 남음).'),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orangeAccent)),
|
||||
// 1280×720 등 낮은 화면에서도 보이게: 원본 지우기 체크 · 경고는 비교 목록보다 위에 (178)
|
||||
if (both) ...[
|
||||
Text(tr('양쪽을 함께: 받는 쪽이 더 새 파일은 덮어쓰지 않습니다 (-u).'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
if (optionMove)
|
||||
Text(tr('양쪽 (⇄) 에서는 원본 파일을 지우지 않습니다 (옵션의 --remove-source-files 는 쓰지 않음).'),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orangeAccent)),
|
||||
] else ...[
|
||||
CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: removeSource,
|
||||
onChanged: (v) => set(() {
|
||||
removeSource = v ?? false;
|
||||
tasks = shownTasks(removeSource);
|
||||
preview = null;
|
||||
previewError = null;
|
||||
}),
|
||||
title: Text(tr('원본 파일 지우기 (--remove-source-files)')),
|
||||
subtitle: Text(tr('대상으로 옮긴 파일을 원본에서 지웁니다 (이동)')),
|
||||
),
|
||||
if (removeSource) ...[
|
||||
// 178: 원본이 지워진다는 것을 분명히 (환경 설정 옵션 때문에 켜졌으면 그렇다고)
|
||||
Text(
|
||||
optionMove
|
||||
? tr('원본 파일이 지워집니다 (이동). 환경 설정의 rsync 옵션에 --remove-source-files 가 있어 켜 두었습니다 - 끄면 이번에는 원본을 남깁니다.')
|
||||
: tr('원본 파일이 지워집니다 (이동).'),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orangeAccent, fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 4),
|
||||
Text(tr('끝난 뒤 원본의 빈 폴더를 지웁니다 (find 원본/ -type d -empty -delete). 원본 폴더는:'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
const SizedBox(height: 6),
|
||||
PruneChoice(value: prune, onChanged: (v) => set(() => prune = v)),
|
||||
],
|
||||
],
|
||||
// 72: 무엇이 바뀌는지 파일별로 (→ · ← · 받는 쪽에만 있음 · 지워짐)
|
||||
const SizedBox(height: 8),
|
||||
SyncPreviewView(
|
||||
|
|
@ -2102,39 +2136,6 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
if (_viaDav([l, r]))
|
||||
Text(tr('WebDAV: rsync 대신 앱이 직접 맞춥니다 (크기 · 바뀐 때 비교, 옵션 중 -u · --delete · --remove-source-files 를 따름).'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.accent)),
|
||||
if (both) ...[
|
||||
Text(tr('양쪽을 함께: 받는 쪽이 더 새 파일은 덮어쓰지 않습니다 (-u).'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
if (optionMove)
|
||||
Text(tr('양쪽 (⇄) 에서는 원본 파일을 지우지 않습니다 (옵션의 --remove-source-files 는 쓰지 않음).'),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orangeAccent)),
|
||||
] else ...[
|
||||
CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: removeSource,
|
||||
onChanged: (v) => set(() {
|
||||
removeSource = v ?? false;
|
||||
tasks = shownTasks(removeSource);
|
||||
preview = null;
|
||||
previewError = null;
|
||||
}),
|
||||
title: Text(tr('원본 파일 지우기 (--remove-source-files)')),
|
||||
subtitle: Text(tr('대상으로 옮긴 파일을 원본에서 지웁니다 (이동)')),
|
||||
),
|
||||
if (removeSource) ...[
|
||||
// 178: 원본이 지워진다는 것을 분명히 (환경 설정 옵션 때문에 켜졌으면 그렇다고)
|
||||
Text(
|
||||
optionMove
|
||||
? tr('원본 파일이 지워집니다 (이동). 환경 설정의 rsync 옵션에 --remove-source-files 가 있어 켜 두었습니다 - 끄면 이번에는 원본을 남깁니다.')
|
||||
: tr('원본 파일이 지워집니다 (이동).'),
|
||||
style: const TextStyle(fontSize: 12, color: Colors.orangeAccent, fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 4),
|
||||
Text(tr('끝난 뒤 원본의 빈 폴더를 지웁니다 (find 원본/ -type d -empty -delete). 원본 폴더는:'),
|
||||
style: const TextStyle(fontSize: 12, color: JjColors.textDim)),
|
||||
const SizedBox(height: 6),
|
||||
PruneChoice(value: prune, onChanged: (v) => set(() => prune = v)),
|
||||
],
|
||||
],
|
||||
]),
|
||||
),
|
||||
actions: [
|
||||
|
|
|
|||
|
|
@ -69,9 +69,13 @@ class _SyncPreviewViewState extends State<SyncPreviewView> {
|
|||
/// 110: 비교 중 · 끝 · 오류 어느 때나 같은 높이 (창 크기가 바뀌어 [취소] · [실행] 자리가 움직이지 않게)
|
||||
static const height = 300.0;
|
||||
|
||||
/// 낮은 화면 (예: 1280×720) 에서는 화면 높이의 28% 까지만 - 아래의 [원본 파일 지우기] · 경고 · 버튼이 가려지지 않게.
|
||||
/// 같은 화면 크기에서는 늘 같은 높이 (110)
|
||||
double get _h => (MediaQuery.sizeOf(context).height * 0.28).clamp(140.0, height);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
SizedBox(height: height, child: Align(alignment: Alignment.topLeft, child: _body()));
|
||||
SizedBox(height: _h, child: Align(alignment: Alignment.topLeft, child: _body()));
|
||||
|
||||
Widget _body() {
|
||||
final items = _items;
|
||||
|
|
@ -116,7 +120,7 @@ class _SyncPreviewViewState extends State<SyncPreviewView> {
|
|||
if (items.isNotEmpty)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 6),
|
||||
constraints: const BoxConstraints(maxHeight: height - 80),
|
||||
constraints: BoxConstraints(maxHeight: _h - 80),
|
||||
decoration: BoxDecoration(color: JjColors.bg, borderRadius: BorderRadius.circular(6)),
|
||||
padding: const EdgeInsets.all(8),
|
||||
// 창 (AlertDialog) 이 크기를 미리 재므로 ListView 대신 (500줄까지)
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ void main() {
|
|||
tmp.deleteSync(recursive: true);
|
||||
});
|
||||
|
||||
Future<void> pump(WidgetTester tester, Widget page) async {
|
||||
Future<void> pump(WidgetTester tester, Widget page, {Size size = const Size(1600, 900)}) async {
|
||||
HttpOverrides.global = null; // testWidgets 는 HttpClient 를 막아 둔다 - 이 시험은 실제 (로컬) 서버에 연결
|
||||
tester.view.physicalSize = const Size(1600, 900);
|
||||
tester.view.physicalSize = size;
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
await tester.runAsync(() => tester.pumpWidget(MaterialApp(home: page)));
|
||||
|
|
@ -123,7 +123,8 @@ void main() {
|
|||
..rsyncOptions = '-av --remove-source-files'
|
||||
..rsyncPaths = [left, 'dav://nas/'];
|
||||
DavRegistry.configure([s]);
|
||||
await pump(tester, ExplorerPage(c: c, rsync: true));
|
||||
// 1280×720 (낮은 창) 에서도 체크 · 경고가 버튼에 가려지지 않게
|
||||
await pump(tester, ExplorerPage(c: c, rsync: true), size: const Size(1280, 720));
|
||||
await settle(tester, () => find.text('sub').evaluate().isNotEmpty && find.text('원격').evaluate().isNotEmpty);
|
||||
await act(tester, () => tester.tap(find.text('sub')));
|
||||
await act(tester, () => tester.tap(find.text('원격')));
|
||||
|
|
@ -136,6 +137,9 @@ void main() {
|
|||
expect(find.widgetWithText(FilledButton, '이동'), findsOneWidget);
|
||||
expect(find.textContaining('원본 파일이 지워집니다 (이동). 환경 설정의 rsync 옵션에'), findsOneWidget);
|
||||
expect(find.text('rsync -av --remove-source-files'), findsOneWidget);
|
||||
final buttonsTop = tester.getRect(find.widgetWithText(FilledButton, '이동')).top;
|
||||
expect(tester.getRect(find.byType(CheckboxListTile)).bottom, lessThan(buttonsTop));
|
||||
expect(tester.getRect(find.textContaining('원본 파일이 지워집니다')).bottom, lessThan(buttonsTop));
|
||||
// 끄면 [실행] · 옵션 줄에서도 빠진다
|
||||
await tester.tap(find.byType(CheckboxListTile));
|
||||
await settle(tester, () => find.textContaining('비교하는 중').evaluate().isEmpty, rounds: 400);
|
||||
|
|
|
|||
Loading…
Reference in New Issue