탐색기 뒤로 · 앞으로를 실제 Windows 에서 한 칸씩 (75) · 이름으로 접지 않기 (189)
- 75 (버그 수정, 실제 Windows 빌드에서 재현): 창 위의 마우스 4 · 5 누름을 창과 화면이 둘 다 받아 두 칸씩 움직였다 (받는 곳마다 좌표를 바꾼 새 이벤트라 identical 로 막히지 않음) → 누른 손가락 · 시각으로 한 번만. 이동이 끝나기 전에 다시 불리면 무시 (내역에서 두 칸이 빠지지 않게). - 75: 지운 폴더로 뒤로 · 앞으로 하면 그 상위 폴더를 두 창 모두 다시 읽는다 (트리에 지운 폴더가 남지 않게) - 189 (관리자 지시): 폴더 이름을 누르면 그 폴더로 (닫혀 있으면 펼침), 이름으로는 접지 않는다. 다시 누르거나 두 번 눌러도 아래 줄이 움직이지 않게. 접기 · 펼치기는 화살표로 (Windows · Android 같게) - 시험: 이름을 다시 · 두 번 눌러도 그대로, 화살표로 접기. 지운 폴더가 트리에서도 사라짐 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>fix_mkv
parent
3639aa9cbf
commit
a7632a9bed
|
|
@ -738,8 +738,12 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
|
||||
/// 75: 창마다 뒤로 · 앞으로 (가 본 폴더로)
|
||||
Future<void> _travel(_Pane pane, {required bool forward}) async {
|
||||
// 앞의 이동이 끝나기 전에 또 불리면 (빨리 두 번 · 같은 누름이 두 번 들어옴) 무시 - 내역에서 두 칸이 빠지지 않게
|
||||
if (pane.traveling) return;
|
||||
final from = forward ? pane.forward : pane.back;
|
||||
if (from.isEmpty) return;
|
||||
pane.traveling = true;
|
||||
try {
|
||||
final to = from.removeLast();
|
||||
setState(() => _active = _panes.indexOf(pane));
|
||||
// 지워졌거나 열 수 없는 폴더: 그 항목은 버리고 지금 폴더는 그대로 (이유를 알림)
|
||||
|
|
@ -751,13 +755,17 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
}
|
||||
if (!mounted) return;
|
||||
if (!ok) {
|
||||
// 트리에도 남지 않게 (밖에서 지운 폴더) - 그 상위 폴더를 두 창 모두 다시 읽는다
|
||||
for (final x in _panes) {
|
||||
x.expanded.removeWhere((d) => samePath(d, to) || d.toLowerCase().startsWith('${to.toLowerCase()}${isDav(to) ? '/' : p.separator}'));
|
||||
}
|
||||
await _refreshAll([vDirname(to)]);
|
||||
if (!mounted) return;
|
||||
setState(() {});
|
||||
_snack(trf('{0} 폴더가 없거나 열 수 없어 내역에서 뺐습니다', [_displayPath(to)]));
|
||||
return;
|
||||
}
|
||||
(forward ? pane.back : pane.forward).add(pane.current);
|
||||
pane.traveling = true;
|
||||
try {
|
||||
await _goTo(pane, to);
|
||||
} finally {
|
||||
pane.traveling = false;
|
||||
|
|
@ -990,7 +998,16 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
return;
|
||||
}
|
||||
if (e.isDir) {
|
||||
// 189: 이름을 누르면 그 폴더로 (닫혀 있으면 펼친다). 이름으로는 접지 않는다 - 다시 누르거나 두 번 누르면 접혀
|
||||
// 아래 줄이 움직여 다른 것을 누르게 된다. 접기 · 펼치기는 › 화살표로 (탐색기 · Total Commander 처럼)
|
||||
if (!pane.expanded.contains(e.path)) {
|
||||
await _toggle(pane, e);
|
||||
} else if (!samePath(pane.current, e.path)) {
|
||||
pane
|
||||
..current = e.path
|
||||
..changed();
|
||||
_remember(pane, e.path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!list) pane.current = vDirname(e.path);
|
||||
|
|
@ -2706,10 +2723,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
autofocus: true,
|
||||
child: Listener(
|
||||
// 75: 마우스 4 · 5번 (뒤로 · 앞으로) 버튼 - 창 밖 (위 막대 등) 이면 지금 창 (창 위면 그 창이 먼저 받음, [_frame])
|
||||
onPointerDown: (ev) {
|
||||
if (identical(ev, _navEvent)) return;
|
||||
_mouseTravel(_active, ev);
|
||||
},
|
||||
onPointerDown: (ev) => _mouseTravel(_active, ev),
|
||||
child: Scaffold(
|
||||
body: SwipeNav(
|
||||
current: widget.rsync ? 'rsync' : 'explorer',
|
||||
|
|
@ -2833,17 +2847,18 @@ class _ExplorerPageState extends State<ExplorerPage> {
|
|||
/// 180: 왼쪽 창 · 오른쪽 창 · 파일 목록 (배치가 바뀌어도 같은 위젯 - [_body])
|
||||
final _viewKeys = [GlobalKey(), GlobalKey(), GlobalKey()];
|
||||
|
||||
/// 75: 마우스 4 · 5번 - 그 창의 뒤로 · 앞으로 (그 창을 활성으로)
|
||||
PointerDownEvent? _navEvent;
|
||||
/// 75: 마우스 4 · 5번 - 그 창의 뒤로 · 앞으로 (그 창을 활성으로).
|
||||
/// 창 위의 누름은 창 ([_frame]) 과 화면 Listener 가 둘 다 받는다. 받는 곳마다 좌표를 바꾼 새 이벤트라 객체로는 같은지 알 수 없어
|
||||
/// 누른 손가락 (pointer) · 시각으로 한 번만 쓴다 (창이 먼저 받는다)
|
||||
(int, Duration)? _navPress;
|
||||
void _mouseTravel(int i, PointerDownEvent ev) {
|
||||
if (i >= _panes.length) return;
|
||||
if (ev.buttons & kBackMouseButton != 0) {
|
||||
_navEvent = ev;
|
||||
_travel(_panes[i], forward: false);
|
||||
} else if (ev.buttons & kForwardMouseButton != 0) {
|
||||
_navEvent = ev;
|
||||
_travel(_panes[i], forward: true);
|
||||
}
|
||||
final back = ev.buttons & kBackMouseButton != 0;
|
||||
if (!back && ev.buttons & kForwardMouseButton == 0) return;
|
||||
final press = (ev.pointer, ev.timeStamp);
|
||||
if (press == _navPress) return;
|
||||
_navPress = press;
|
||||
_travel(_panes[i], forward: !back);
|
||||
}
|
||||
|
||||
Widget _frame(int i, List<Widget> children) {
|
||||
|
|
|
|||
|
|
@ -80,14 +80,21 @@ void main() {
|
|||
expect(find.text('모니터링'), findsNothing);
|
||||
expect(find.text('좌 → 우'), findsNothing);
|
||||
|
||||
// 폴더를 한 번 누르면 바로 펼치고, 다시 누르면 접는다
|
||||
// 폴더를 한 번 누르면 바로 펼친다. 189: 다시 눌러도 (두 번 누름 포함) 접지 않는다 - 접기 · 펼치기는 화살표로
|
||||
await act(tester, () => tester.tap(find.text('sub')));
|
||||
await settle(tester, () => find.text('inner.txt').evaluate().isNotEmpty);
|
||||
expect(find.text('inner.txt'), findsOneWidget);
|
||||
await act(tester, () => tester.tap(find.text('sub')));
|
||||
await settle(tester, () => false, rounds: 15);
|
||||
expect(find.text('inner.txt'), findsOneWidget, reason: '이름을 다시 눌러도 그대로');
|
||||
await doubleTap(tester, find.text('sub'));
|
||||
await settle(tester, () => false, rounds: 15);
|
||||
expect(find.text('inner.txt'), findsOneWidget, reason: '두 번 눌러도 그대로');
|
||||
await act(tester, () => tester.tap(find.descendant(
|
||||
of: find.ancestor(of: find.text('sub'), matching: find.byType(InkWell)).first, matching: find.byIcon(Icons.expand_more))));
|
||||
await settle(tester, () => find.text('inner.txt').evaluate().isEmpty);
|
||||
expect(find.text('inner.txt'), findsNothing);
|
||||
// › 화살표로도 펼친다
|
||||
expect(find.text('inner.txt'), findsNothing, reason: '화살표로 접는다');
|
||||
// › 화살표로 펼친다
|
||||
await act(tester, () => tester.tap(chevronOf('sub')));
|
||||
await settle(tester, () => find.text('inner.txt').evaluate().isNotEmpty);
|
||||
expect(find.text('inner.txt'), findsOneWidget);
|
||||
|
|
@ -476,10 +483,13 @@ void main() {
|
|||
await act(tester, () => tester.tap(find.byTooltip('뒤로 (Alt+←)').first));
|
||||
await settle(tester, () => now() == left, rounds: 50);
|
||||
await tester.runAsync(() => Directory(sub).delete(recursive: true));
|
||||
expect(find.text('sub'), findsOneWidget, reason: '밖에서 지운 것은 아직 모름');
|
||||
await act(tester, () => tester.tap(find.byTooltip('앞으로 (Alt+→)').first));
|
||||
await settle(tester, () => find.textContaining('내역에서 뺐습니다').evaluate().isNotEmpty, rounds: 50);
|
||||
expect(find.textContaining('내역에서 뺐습니다'), findsOneWidget);
|
||||
expect(now(), left);
|
||||
await settle(tester, () => find.text('sub').evaluate().isEmpty, rounds: 50);
|
||||
expect(find.text('sub'), findsNothing, reason: '트리에도 남지 않음 (상위 폴더를 다시 읽음)');
|
||||
// 버린 항목은 다시 가지 않는다 (앞으로 버튼이 꺼짐)
|
||||
final fwd = tester.widget<IconButton>(find.ancestor(of: find.byTooltip('앞으로 (Alt+→)').first, matching: find.byType(IconButton)).first);
|
||||
expect(fwd.onPressed, isNull);
|
||||
|
|
|
|||
Loading…
Reference in New Issue