left shift key for peer card select

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2023-08-04 13:11:24 +08:00
parent 5a0865559c
commit f5cf291f55
3 changed files with 66 additions and 10 deletions

View File

@ -68,7 +68,7 @@ class _PeerCardState extends State<_PeerCard>
child: GestureDetector(
onTap: () {
if (peerTabModel.multiSelectionMode) {
peerTabModel.onPeerCardTap(peer);
peerTabModel.togglePeerSelect(peer);
} else {
if (!isWebDesktop) connect(context, peer.id);
}
@ -167,7 +167,7 @@ class _PeerCardState extends State<_PeerCard>
peerTabModel.togglePeerSelect(peer);
},
onTap: peerTabModel.multiSelectionMode
? () => peerTabModel.onPeerCardTap(peer)
? () => peerTabModel.togglePeerSelect(peer)
: null,
child: Obx(() => peerCardUiType.value == PeerUiType.grid
? _buildPeerCard(context, peer, deco)

View File

@ -5,6 +5,7 @@ import 'dart:io';
import 'package:bot_toast/bot_toast.dart';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
import 'package:flutter_hbb/desktop/pages/install_page.dart';
import 'package:flutter_hbb/desktop/pages/server_page.dart';
@ -417,6 +418,9 @@ class _AppState extends State<App> {
: (context, child) {
child = _keepScaleBuilder(context, child);
child = botToastBuilder(context, child);
if (desktopType == DesktopType.main) {
child = keyListenerBuilder(context, child);
}
return child;
},
),
@ -453,3 +457,19 @@ _registerEventHandler() {
});
}
}
Widget keyListenerBuilder(BuildContext context, Widget? child) {
return RawKeyboardListener(
focusNode: FocusNode(),
child: child ?? Container(),
onKey: (RawKeyEvent event) {
if (event.logicalKey == LogicalKeyboardKey.shiftLeft) {
if (event is RawKeyDownEvent) {
gFFI.peerTabModel.isShiftDown = true;
} else if (event is RawKeyUpEvent) {
gFFI.peerTabModel.isShiftDown = false;
}
}
},
);
}

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/models/peer_model.dart';
import 'package:flutter_hbb/models/platform_model.dart';
@ -40,6 +42,8 @@ class PeerTabModel with ChangeNotifier {
bool get multiSelectionMode => _selectedPeers.isNotEmpty;
List<Peer> _currentTabCachedPeers = List.empty(growable: true);
List<Peer> get currentTabCachedPeers => _currentTabCachedPeers;
bool isShiftDown = false;
String? _shiftAnchorId;
PeerTabModel(this.parent) {
// init currentTab
@ -82,21 +86,53 @@ class PeerTabModel with ChangeNotifier {
}
togglePeerSelect(Peer peer) {
if (_selectedPeers.firstWhereOrNull((p) => p.id == peer.id) != null) {
_selectedPeers.removeWhere((p) => p.id == peer.id);
final cached = _currentTabCachedPeers.map((e) => e.id).toList();
int thisIndex = cached.indexOf(peer.id);
int closestIndex = -1;
String? closestId;
int smallestDiff = -1;
for (var i = 0; i < cached.length; i++) {
if (isPeerSelected(cached[i])) {
int diff = (i - thisIndex).abs();
if (smallestDiff == -1 || diff < smallestDiff) {
closestIndex = i;
closestId = cached[i];
smallestDiff = diff;
}
}
}
if (isShiftDown &&
thisIndex >= 0 &&
closestIndex >= 0 &&
closestId != null) {
int shiftAnchorIndex = cached.indexOf(_shiftAnchorId ?? '');
if (shiftAnchorIndex < 0) {
// use closest as shift anchor, rather than focused which we don't have
shiftAnchorIndex = closestIndex;
_shiftAnchorId = closestId;
}
int start = min(shiftAnchorIndex, thisIndex);
int end = max(shiftAnchorIndex, thisIndex);
_selectedPeers.clear();
for (var i = start; i <= end; i++) {
if (!isPeerSelected(cached[i])) {
_selectedPeers.add(_currentTabCachedPeers[i]);
}
}
} else {
_selectedPeers.add(peer);
if (isPeerSelected(peer.id)) {
_selectedPeers.removeWhere((p) => p.id == peer.id);
} else {
_selectedPeers.add(peer);
}
_shiftAnchorId = null;
}
notifyListeners();
}
onPeerCardTap(Peer peer) {
if (!multiSelectionMode) return;
togglePeerSelect(peer);
}
closeSelection() {
_selectedPeers.clear();
_shiftAnchorId = null;
notifyListeners();
}