right menu to show/hide peer card

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-12-04 15:15:48 +08:00
parent fb0c75f188
commit be74f90334
31 changed files with 198 additions and 101 deletions

View File

@ -1,36 +1,73 @@
import 'dart:ui' as ui;
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common/widgets/address_book.dart';
import 'package:flutter_hbb/common/widgets/peers_view.dart';
import 'package:flutter_hbb/common/widgets/peer_card.dart';
import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/desktop/widgets/popup_menu.dart';
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
import 'package:flutter_hbb/desktop/widgets/material_mod_popup_menu.dart'
as mod_menu;
import 'package:get/get.dart';
import '../../common.dart';
import '../../models/platform_model.dart';
class PeerTabPage extends StatefulWidget {
final List<String> tabs;
final List<Widget> children;
const PeerTabPage({required this.tabs, required this.children, Key? key})
: super(key: key);
const PeerTabPage({Key? key}) : super(key: key);
@override
State<PeerTabPage> createState() => _PeerTabPageState();
}
class _TabEntry {
final String name;
final Widget widget;
final Function() load;
_TabEntry(this.name, this.widget, this.load);
}
class _PeerTabPageState extends State<PeerTabPage>
with SingleTickerProviderStateMixin {
final RxInt _tabIndex = 0.obs;
late final RxInt _tabHiddenFlag;
late final RxString _currentTab;
final List<_TabEntry> entries = [
_TabEntry(
'Recent Sessions',
RecentPeersView(
menuPadding: kDesktopMenuPadding,
),
bind.mainLoadRecentPeers),
_TabEntry(
'Favorites',
FavoritePeersView(
menuPadding: kDesktopMenuPadding,
),
bind.mainLoadFavPeers),
_TabEntry(
'Discovered',
DiscoveredPeersView(
menuPadding: kDesktopMenuPadding,
),
bind.mainDiscover),
_TabEntry(
'Address Book',
const AddressBook(
menuPadding: kDesktopMenuPadding,
),
() => {}),
];
@override
void initState() {
setPeer();
super.initState();
}
setPeer() {
final index = bind.getLocalFlutterConfig(k: 'peer-tab-index');
if (index != '') {
_tabIndex.value = int.parse(index);
}
_tabHiddenFlag = (int.tryParse(
bind.getLocalFlutterConfig(k: 'hidden-peer-card'),
radix: 2) ??
0)
.obs;
_currentTab = bind.getLocalFlutterConfig(k: 'current-peer-tab').obs;
adjustTab();
final uiType = bind.getLocalFlutterConfig(k: 'peer-card-ui-type');
if (uiType != '') {
@ -38,27 +75,14 @@ class _PeerTabPageState extends State<PeerTabPage>
? PeerUiType.list
: PeerUiType.grid;
}
super.initState();
}
// hard code for now
Future<void> _handleTabSelection(int index) async {
_tabIndex.value = index;
await bind.setLocalFlutterConfig(k: 'peer-tab-index', v: index.toString());
switch (index) {
case 0:
bind.mainLoadRecentPeers();
break;
case 1:
bind.mainLoadFavPeers();
break;
case 2:
bind.mainDiscover();
break;
case 3:
/// AddressBook initState will refresh ab state
break;
}
Future<void> handleTabSelection(String tabName) async {
_currentTab.value = tabName;
await bind.setLocalFlutterConfig(k: 'current-peer-tab', v: tabName);
entries.firstWhereOrNull((e) => e.name == tabName)?.load();
}
@override
@ -80,8 +104,9 @@ class _PeerTabPageState extends State<PeerTabPage>
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: _createSwitchBar(context)),
const SizedBox(width: 10),
Expanded(
child: visibleContextMenuListener(
_createSwitchBar(context))),
const PeerSearchBar(),
Offstage(
offstage: !isDesktop,
@ -97,44 +122,48 @@ class _PeerTabPageState extends State<PeerTabPage>
Widget _createSwitchBar(BuildContext context) {
final textColor = Theme.of(context).textTheme.titleLarge?.color;
return ListView(
return Obx(() => ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
controller: ScrollController(),
children: super.widget.tabs.asMap().entries.map((t) {
return Obx(() => InkWell(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: _tabIndex.value == t.key
? Theme.of(context).backgroundColor
: null,
borderRadius: BorderRadius.circular(isDesktop ? 2 : 6),
),
child: Align(
alignment: Alignment.center,
child: Text(
t.value,
textAlign: TextAlign.center,
style: TextStyle(
height: 1,
fontSize: 14,
color:
_tabIndex.value == t.key ? textColor : textColor
?..withOpacity(0.5)),
),
)),
onTap: () async => await _handleTabSelection(t.key),
));
}).toList());
children: entries.where((e) => !isTabHidden(e.name)).map((t) {
return InkWell(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: _currentTab.value == t.name
? Theme.of(context).backgroundColor
: null,
borderRadius: BorderRadius.circular(isDesktop ? 2 : 6),
),
child: Align(
alignment: Alignment.center,
child: Text(
translate(t.name),
textAlign: TextAlign.center,
style: TextStyle(
height: 1,
fontSize: 14,
color:
_currentTab.value == t.name ? textColor : textColor
?..withOpacity(0.5)),
),
)),
onTap: () async => await handleTabSelection(t.name),
);
}).toList()));
}
Widget _createPeersView() {
final verticalMargin = isDesktop ? 12.0 : 6.0;
return Expanded(
child: Obx(() => widget
.children[_tabIndex.value]) //: (to) => _tabIndex.value = to)
.marginSymmetric(vertical: verticalMargin),
child: Obx(() =>
entries
.firstWhereOrNull((e) => e.name == _currentTab.value)
?.widget ??
visibleContextMenuListener(Center(
child: Text(translate('Right click to select tabs')),
))).marginSymmetric(vertical: verticalMargin),
);
}
@ -167,6 +196,81 @@ class _PeerTabPageState extends State<PeerTabPage>
.toList(),
);
}
bool isTabHidden(String name) {
int index = entries.indexWhere((e) => e.name == name);
if (index >= 0) {
return _tabHiddenFlag & (1 << index) != 0;
}
assert(false);
return false;
}
adjustTab() {
List<String> visibleTabs =
entries.where((e) => !isTabHidden(e.name)).map((e) => e.name).toList();
if (visibleTabs.isNotEmpty) {
if (!visibleTabs.contains(_currentTab.value)) {
handleTabSelection(visibleTabs[0]);
}
} else {
_currentTab.value = '';
}
}
Widget visibleContextMenuListener(Widget child) {
return Listener(
onPointerDown: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) {
return;
}
if (e.buttons == 2) {
showRightMenu(
(CancelFunc cancelFunc) {
return visibleContextMenu(cancelFunc);
},
target: e.position,
);
}
},
child: child);
}
Widget visibleContextMenu(CancelFunc cancelFunc) {
final List<MenuEntryBase> menu = entries.asMap().entries.map((e) {
int bitMask = 1 << e.key;
return MenuEntrySwitch(
switchType: SwitchType.scheckbox,
text: translate(e.value.name),
getter: () async {
return _tabHiddenFlag.value & bitMask == 0;
},
setter: (show) async {
if (show) {
_tabHiddenFlag.value &= ~bitMask;
} else {
_tabHiddenFlag.value |= bitMask;
}
await bind.setLocalFlutterConfig(
k: 'hidden-peer-card',
v: _tabHiddenFlag.value.toRadixString(2));
cancelFunc();
adjustTab();
});
}).toList();
return mod_menu.PopupMenu(
items: menu
.map((entry) => entry.build(
context,
const MenuConfig(
commonColor: MyTheme.accent,
height: 20.0,
dividerHeight: 12.0,
)))
.expand((i) => i)
.toList(),
);
}
}
class PeerSearchBar extends StatefulWidget {

View File

@ -121,28 +121,7 @@ class _ConnectionPageState extends State<ConnectionPage>
])),
SliverFillRemaining(
hasScrollBody: false,
child: PeerTabPage(
tabs: [
translate('Recent Sessions'),
translate('Favorites'),
translate('Discovered'),
translate('Address Book')
],
children: [
RecentPeersView(
menuPadding: kDesktopMenuPadding,
),
FavoritePeersView(
menuPadding: kDesktopMenuPadding,
),
DiscoveredPeersView(
menuPadding: kDesktopMenuPadding,
),
const AddressBook(
menuPadding: kDesktopMenuPadding,
),
],
).paddingOnly(right: 12.0),
child: PeerTabPage().paddingOnly(right: 12.0),
)
],
).paddingOnly(left: 12.0),

View File

@ -75,20 +75,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
])),
SliverFillRemaining(
hasScrollBody: false,
child: PeerTabPage(
tabs: [
translate('Recent Sessions'),
translate('Favorites'),
translate('Discovered'),
translate('Address Book')
],
children: [
RecentPeersView(),
FavoritePeersView(),
DiscoveredPeersView(),
const AddressBook(),
],
),
child: PeerTabPage(),
)
],
).marginOnly(top: 2, left: 10, right: 10);

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "隐藏连接管理窗口"),
("hide_cm_tip", "在只允许密码连接并且只用固定密码的情况下才允许隐藏"),
("wayland_experiment_tip", ""),
("Right click to select tabs", "右键选择选项卡"),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Ocultar ventana de gestión de conexión"),
("hide_cm_tip", "Permitir ocultar solo si se aceptan sesiones a través de contraseña y usando contraseña permanente"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "پنهان کردن پنجره مدیریت اتصال"),
("hide_cm_tip", "فقط در صورت پذیرفتن جلسات از طریق رمز عبور و استفاده از رمز عبور دائمی، مخفی شدن مجاز است"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Masquer la fenêtre de gestion des connexions"),
("hide_cm_tip", "Autoriser le masquage uniquement si vous acceptez des sessions via un mot de passe et utilisez un mot de passe permanent"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -397,6 +397,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Request access to your device", "Αίτημα πρόσβασης στη συσκευή σας"),
("Hide connection management window", "Απόκρυψη παραθύρου διαχείρισης σύνδεσης"),
("hide_cm_tip", "Να επιτρέπεται η απόκρυψη, μόνο εάν αποδέχεστε συνδέσεις μέσω κωδικού πρόσβασης και χρησιμοποιείτε μόνιμο κωδικό πρόσβασης"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Nascondi la finestra di gestione delle connessioni"),
("hide_cm_tip", "Permetti di nascondere solo se si accettano sessioni con password permanente"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Скрывать окно управления соединениями"),
("hide_cm_tip", "Разрешать скрытие случае, если принимаются сеансы по паролю или используется постоянный пароль"),
("wayland_experiment_tip", "Поддержка Wayland находится на экспериментальной стадии, используйте X11, если вам требуется автоматический доступ."),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Fshih dritaren e menaxhimit të lidhjes"),
("hide_cm_tip", "Kjo është e mundur vetëm nëse aksesi bëhet nëpërmjet një fjalëkalimi të përhershëm"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Göm hanteringsfönster"),
("hide_cm_tip", "Tillåt att gömma endast om accepterande sessioner med lösenord och permanenta lösenord"),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "Bağlantı yönetimi penceresini gizle"),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", "隱藏連接管理窗口"),
("hide_cm_tip", "在只允許密碼連接並且只用固定密碼的情況下才允許隱藏"),
("wayland_experiment_tip", ""),
("Right click to select tabs", "右鍵選擇選項卡"),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}

View File

@ -398,5 +398,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Hide connection management window", ""),
("hide_cm_tip", ""),
("wayland_experiment_tip", ""),
("Right click to select tabs", ""),
].iter().cloned().collect();
}