mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-01 01:29:02 +08:00
commit
f649f8dbcd
@ -215,18 +215,15 @@ class MyTheme {
|
||||
}
|
||||
|
||||
static void changeDarkMode(ThemeMode mode) {
|
||||
final preference = getThemeModePreference();
|
||||
if (preference != mode) {
|
||||
Get.changeThemeMode(mode);
|
||||
if (desktopType == DesktopType.main) {
|
||||
if (mode == ThemeMode.system) {
|
||||
bind.mainSetLocalOption(key: kCommConfKeyTheme, value: '');
|
||||
} else {
|
||||
bind.mainSetLocalOption(
|
||||
key: kCommConfKeyTheme, value: mode.toShortString());
|
||||
}
|
||||
Get.changeThemeMode(mode);
|
||||
if (desktopType == DesktopType.main) {
|
||||
bind.mainChangeTheme(dark: currentThemeMode().toShortString());
|
||||
}
|
||||
bind.mainChangeTheme(dark: currentThemeMode().toShortString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
Text(translate(error)),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
setState(() {});
|
||||
gFFI.abModel.pullAb();
|
||||
},
|
||||
child: Text(translate("Retry")))
|
||||
],
|
||||
|
@ -1,64 +1,107 @@
|
||||
import 'dart:convert';
|
||||
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;
|
||||
late final RxList<String> visibleOrderedTabs;
|
||||
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;
|
||||
visibleOrderedTabs = entries
|
||||
.where((e) => !isTabHidden(e.name))
|
||||
.map((e) => e.name)
|
||||
.toList()
|
||||
.obs;
|
||||
try {
|
||||
final json = jsonDecode(bind.getLocalFlutterConfig(k: 'peer-tab-order'));
|
||||
if (json is List) {
|
||||
final List<String> list = json.map((e) => e.toString()).toList();
|
||||
if (list.length == visibleOrderedTabs.length &&
|
||||
visibleOrderedTabs.every((e) => list.contains(e))) {
|
||||
visibleOrderedTabs.value = list;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
|
||||
adjustTab();
|
||||
|
||||
final uiType = bind.getLocalFlutterConfig(k: 'peer-card-ui-type');
|
||||
if (uiType != '') {
|
||||
peerCardUiType.value = int.parse(uiType) == PeerUiType.list.index
|
||||
? 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 +123,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,16 +141,34 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
|
||||
Widget _createSwitchBar(BuildContext context) {
|
||||
final textColor = Theme.of(context).textTheme.titleLarge?.color;
|
||||
return ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
shrinkWrap: true,
|
||||
controller: ScrollController(),
|
||||
children: super.widget.tabs.asMap().entries.map((t) {
|
||||
return Obx(() => InkWell(
|
||||
return Obx(() {
|
||||
int indexCounter = -1;
|
||||
return ReorderableListView(
|
||||
buildDefaultDragHandles: false,
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
var list = visibleOrderedTabs.toList();
|
||||
if (oldIndex < newIndex) {
|
||||
newIndex -= 1;
|
||||
}
|
||||
final String item = list.removeAt(oldIndex);
|
||||
list.insert(newIndex, item);
|
||||
bind.setLocalFlutterConfig(
|
||||
k: 'peer-tab-order', v: jsonEncode(list));
|
||||
visibleOrderedTabs.value = list;
|
||||
},
|
||||
scrollDirection: Axis.horizontal,
|
||||
shrinkWrap: true,
|
||||
scrollController: ScrollController(),
|
||||
children: visibleOrderedTabs.map((t) {
|
||||
indexCounter++;
|
||||
return ReorderableDragStartListener(
|
||||
key: ValueKey(t),
|
||||
index: indexCounter,
|
||||
child: InkWell(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: _tabIndex.value == t.key
|
||||
color: currentTab.value == t
|
||||
? Theme.of(context).backgroundColor
|
||||
: null,
|
||||
borderRadius: BorderRadius.circular(isDesktop ? 2 : 6),
|
||||
@ -114,27 +176,30 @@ class _PeerTabPageState extends State<PeerTabPage>
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
t.value,
|
||||
translate(t),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 14,
|
||||
color:
|
||||
_tabIndex.value == t.key ? textColor : textColor
|
||||
?..withOpacity(0.5)),
|
||||
color: currentTab.value == t ? textColor : textColor
|
||||
?..withOpacity(0.5)),
|
||||
),
|
||||
)),
|
||||
onTap: () async => await _handleTabSelection(t.key),
|
||||
));
|
||||
}).toList());
|
||||
onTap: () async => await handleTabSelection(t),
|
||||
),
|
||||
);
|
||||
}).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 +232,87 @@ 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() {
|
||||
if (visibleOrderedTabs.isNotEmpty) {
|
||||
if (!visibleOrderedTabs.contains(currentTab.value)) {
|
||||
handleTabSelection(visibleOrderedTabs[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));
|
||||
visibleOrderedTabs.removeWhere((e) => isTabHidden(e));
|
||||
visibleOrderedTabs.addAll(entries
|
||||
.where((e) =>
|
||||
!visibleOrderedTabs.contains(e.name) &&
|
||||
!isTabHidden(e.name))
|
||||
.map((e) => e.name)
|
||||
.toList());
|
||||
await bind.setLocalFlutterConfig(
|
||||
k: 'peer-tab-order', v: jsonEncode(visibleOrderedTabs));
|
||||
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 {
|
||||
|
@ -113,7 +113,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
delegate: SliverChildListDelegate([
|
||||
Row(
|
||||
children: [
|
||||
_buildRemoteIDTextField(context),
|
||||
Flexible(child: _buildRemoteIDTextField(context)),
|
||||
],
|
||||
).marginOnly(top: 22),
|
||||
SizedBox(height: 12),
|
||||
@ -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),
|
||||
@ -258,9 +237,8 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
),
|
||||
),
|
||||
);
|
||||
return Center(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 600), child: w));
|
||||
return Container(
|
||||
constraints: const BoxConstraints(maxWidth: 600), child: w);
|
||||
}
|
||||
|
||||
Widget buildStatus() {
|
||||
|
@ -238,7 +238,7 @@ Widget buildConnectionCard(Client client) {
|
||||
key: ValueKey(client.id),
|
||||
children: [
|
||||
_CmHeader(client: client),
|
||||
client.isFileTransfer || client.disconnected
|
||||
client.type_() != ClientType.remote || client.disconnected
|
||||
? Offstage()
|
||||
: _PrivilegeBoard(client: client),
|
||||
Expanded(
|
||||
@ -376,7 +376,7 @@ class _CmHeaderState extends State<_CmHeader>
|
||||
),
|
||||
),
|
||||
Offstage(
|
||||
offstage: !client.authorized || client.isFileTransfer,
|
||||
offstage: !client.authorized || client.type_() != ClientType.remote,
|
||||
child: IconButton(
|
||||
onPressed: () => checkClickTime(
|
||||
client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)),
|
||||
@ -510,7 +510,9 @@ class _CmControlPanel extends StatelessWidget {
|
||||
buildAuthorized(BuildContext context) {
|
||||
final bool canElevate = bind.cmCanElevate();
|
||||
final model = Provider.of<ServerModel>(context);
|
||||
final showElevation = canElevate && model.showElevation;
|
||||
final showElevation = canElevate &&
|
||||
model.showElevation &&
|
||||
client.type_() == ClientType.remote;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
@ -560,7 +562,9 @@ class _CmControlPanel extends StatelessWidget {
|
||||
buildUnAuthorized(BuildContext context) {
|
||||
final bool canElevate = bind.cmCanElevate();
|
||||
final model = Provider.of<ServerModel>(context);
|
||||
final showElevation = canElevate && model.showElevation;
|
||||
final showElevation = canElevate &&
|
||||
model.showElevation &&
|
||||
client.type_() == ClientType.remote;
|
||||
final showAccept = model.approveMode != 'password';
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
|
@ -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);
|
||||
|
@ -34,13 +34,20 @@ class AbModel {
|
||||
if (resp.body.isNotEmpty && resp.body.toLowerCase() != "null") {
|
||||
Map<String, dynamic> json = jsonDecode(resp.body);
|
||||
if (json.containsKey('error')) {
|
||||
abError = json['error'];
|
||||
abError.value = json['error'];
|
||||
} else if (json.containsKey('data')) {
|
||||
final data = jsonDecode(json['data']);
|
||||
tags.value = data['tags'];
|
||||
peers.clear();
|
||||
for (final peer in data['peers']) {
|
||||
peers.add(Peer.fromJson(peer));
|
||||
if (data != null) {
|
||||
tags.clear();
|
||||
peers.clear();
|
||||
if (data['tags'] is List) {
|
||||
tags.value = data['tags'];
|
||||
}
|
||||
if (data['peers'] is List) {
|
||||
for (final peer in data['peers']) {
|
||||
peers.add(Peer.fromJson(peer));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resp.body;
|
||||
|
@ -581,10 +581,17 @@ class ServerModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClientType {
|
||||
remote,
|
||||
file,
|
||||
portForward,
|
||||
}
|
||||
|
||||
class Client {
|
||||
int id = 0; // client connections inner count id
|
||||
bool authorized = false;
|
||||
bool isFileTransfer = false;
|
||||
String portForward = "";
|
||||
String name = "";
|
||||
String peerId = ""; // peer user's id,show at app
|
||||
bool keyboard = false;
|
||||
@ -604,6 +611,7 @@ class Client {
|
||||
id = json['id'];
|
||||
authorized = json['authorized'];
|
||||
isFileTransfer = json['is_file_transfer'];
|
||||
portForward = json['port_forward'];
|
||||
name = json['name'];
|
||||
peerId = json['peer_id'];
|
||||
keyboard = json['keyboard'];
|
||||
@ -620,6 +628,7 @@ class Client {
|
||||
data['id'] = id;
|
||||
data['is_start'] = authorized;
|
||||
data['is_file_transfer'] = isFileTransfer;
|
||||
data['port_forward'] = portForward;
|
||||
data['name'] = name;
|
||||
data['peer_id'] = peerId;
|
||||
data['keyboard'] = keyboard;
|
||||
@ -631,6 +640,16 @@ class Client {
|
||||
data['disconnected'] = disconnected;
|
||||
return data;
|
||||
}
|
||||
|
||||
ClientType type_() {
|
||||
if (isFileTransfer) {
|
||||
return ClientType.file;
|
||||
} else if (portForward.isNotEmpty) {
|
||||
return ClientType.portForward;
|
||||
} else {
|
||||
return ClientType.remote;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getLoginDialogTag(int id) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class Body: Reactor.Component
|
||||
};
|
||||
var right_style = show_chat ? "" : "display: none";
|
||||
var disconnected = c.disconnected;
|
||||
var show_elevation_btn = handler.can_elevate() && show_elevation;
|
||||
var show_elevation_btn = handler.can_elevate() && show_elevation && !c.is_file_transfer && c.port_forward.length == 0;
|
||||
var show_accept_btn = handler.get_option('approve-mode') != 'password';
|
||||
// below size:* is work around for Linux, it alreayd set in css, but not work, shit sciter
|
||||
return <div .content style="size:*">
|
||||
|
@ -200,7 +200,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
h265 = h265 && encoding_265;
|
||||
return (h264, h265);
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
#[allow(unreachable_code)]
|
||||
(false, false)
|
||||
}
|
||||
|
||||
@ -1211,7 +1211,13 @@ impl<T: InvokeUiSession> Interface for Session<T> {
|
||||
input_os_password(p, true, self.clone());
|
||||
}
|
||||
let current = &pi.displays[pi.current_display as usize];
|
||||
self.set_display(current.x, current.y, current.width, current.height, current.cursor_embeded);
|
||||
self.set_display(
|
||||
current.x,
|
||||
current.y,
|
||||
current.width,
|
||||
current.height,
|
||||
current.cursor_embeded,
|
||||
);
|
||||
}
|
||||
self.update_privacy_mode();
|
||||
// Save recent peers, then push event to flutter. So flutter can refresh peer page.
|
||||
|
Loading…
Reference in New Issue
Block a user