diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart index 73660cc3..12405766 100644 --- a/flutter/lib/common/widgets/peer_card.dart +++ b/flutter/lib/common/widgets/peer_card.dart @@ -42,6 +42,7 @@ class _PeerCardState extends State<_PeerCard> with AutomaticKeepAliveClientMixin { var _menuPos = RelativeRect.fill; final double _cardRadius = 16; + final double _tileRadius = 5; final double _borderWidth = 2; @override @@ -116,27 +117,32 @@ class _PeerCardState extends State<_PeerCard> Widget _buildDesktop() { final peer = super.widget.peer; - var deco = Rx(BoxDecoration( + var deco = Rx( + BoxDecoration( border: Border.all(color: Colors.transparent, width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null)); + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ), + ); return MouseRegion( onEnter: (evt) { deco.value = BoxDecoration( - border: Border.all( - color: Theme.of(context).colorScheme.primary, - width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null); + border: Border.all( + color: Theme.of(context).colorScheme.primary, + width: _borderWidth), + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ); }, onExit: (evt) { deco.value = BoxDecoration( - border: Border.all(color: Colors.transparent, width: _borderWidth), - borderRadius: peerCardUiType.value == PeerUiType.grid - ? BorderRadius.circular(_cardRadius) - : null); + border: Border.all(color: Colors.transparent, width: _borderWidth), + borderRadius: BorderRadius.circular( + peerCardUiType.value == PeerUiType.grid ? _cardRadius : _tileRadius, + ), + ); }, child: GestureDetector( onDoubleTap: () => widget.connect(context, peer.id), @@ -163,6 +169,10 @@ class _PeerCardState extends State<_PeerCard> Container( decoration: BoxDecoration( color: str2color('${peer.id}${peer.platform}', 0x7f), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(_tileRadius), + bottomLeft: Radius.circular(_tileRadius), + ), ), alignment: Alignment.center, width: 42, @@ -171,7 +181,12 @@ class _PeerCardState extends State<_PeerCard> Expanded( child: Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background), + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.only( + topRight: Radius.circular(_tileRadius), + bottomRight: Radius.circular(_tileRadius), + ), + ), child: Row( children: [ Expanded( diff --git a/flutter/lib/common/widgets/peer_tab_page.dart b/flutter/lib/common/widgets/peer_tab_page.dart index da7e37e6..869bd5fd 100644 --- a/flutter/lib/common/widgets/peer_tab_page.dart +++ b/flutter/lib/common/widgets/peer_tab_page.dart @@ -17,6 +17,7 @@ import 'package:get/get.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:provider/provider.dart'; import 'package:visibility_detector/visibility_detector.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import '../../common.dart'; import '../../models/platform_model.dart'; @@ -39,6 +40,8 @@ EdgeInsets? _menuPadding() { class _PeerTabPageState extends State with SingleTickerProviderStateMixin { + bool _hideSort = bind.getLocalFlutterConfig(k: 'peer-tab-index') == '0'; + final List<_TabEntry> entries = [ _TabEntry( RecentPeersView( @@ -83,6 +86,7 @@ class _PeerTabPageState extends State if (tabIndex < entries.length) { gFFI.peerTabModel.setCurrentTab(tabIndex); entries[tabIndex].load(); + _hideSort = tabIndex == 0; } } @@ -95,22 +99,27 @@ class _PeerTabPageState extends State SizedBox( height: 28, child: Container( - padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), - constraints: isDesktop ? null : kMobilePageConstraints, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: visibleContextMenuListener( - _createSwitchBar(context))), - buildScrollJumper(), - const PeerSearchBar(), - Offstage( - offstage: !isDesktop, - child: _createPeerViewTypeSwitch(context) - .marginOnly(left: 13)), - ], - )), + padding: isDesktop ? null : EdgeInsets.symmetric(horizontal: 2), + constraints: isDesktop ? null : kMobilePageConstraints, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: + visibleContextMenuListener(_createSwitchBar(context))), + buildScrollJumper(), + const PeerSearchBar(), + Offstage( + offstage: !isDesktop, + child: _createPeerViewTypeSwitch(context) + .marginOnly(left: 13)), + Offstage( + offstage: _hideSort, + child: PeerSortDropdown().marginOnly(left: 8), + ), + ], + ), + ), ), _createPeersView(), ], @@ -231,32 +240,32 @@ class _PeerTabPageState extends State Widget _createPeerViewTypeSwitch(BuildContext context) { final textColor = Theme.of(context).textTheme.titleLarge?.color; - final activeDeco = - BoxDecoration(color: Theme.of(context).colorScheme.background); - return Row( - children: [PeerUiType.grid, PeerUiType.list] - .map((type) => Obx( - () => Container( - padding: EdgeInsets.all(4.0), - decoration: peerCardUiType.value == type ? activeDeco : null, - child: InkWell( - onTap: () async { - await bind.setLocalFlutterConfig( - k: 'peer-card-ui-type', v: type.index.toString()); - peerCardUiType.value = type; - }, - child: Icon( - type == PeerUiType.grid - ? Icons.grid_view_rounded - : Icons.list, - size: 18, - color: - peerCardUiType.value == type ? textColor : textColor - ?..withOpacity(0.5), - )), - ), - )) - .toList(), + final deco = BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.circular(5), + ); + final types = [PeerUiType.grid, PeerUiType.list]; + + return Obx( + () => Container( + padding: EdgeInsets.all(4.0), + decoration: deco, + child: InkWell( + onTap: () async { + final type = types.elementAt( + peerCardUiType.value == types.elementAt(0) ? 1 : 0); + await bind.setLocalFlutterConfig( + k: 'peer-card-ui-type', v: type.index.toString()); + peerCardUiType.value = type; + }, + child: Icon( + peerCardUiType.value == PeerUiType.grid + ? Icons.list_rounded + : Icons.grid_view_rounded, + size: 18, + color: textColor, + )), + ), ); } @@ -417,3 +426,90 @@ class _PeerSearchBarState extends State { ); } } + +class PeerSortDropdown extends StatefulWidget { + const PeerSortDropdown({super.key}); + + @override + State createState() => _PeerSortDropdownState(); +} + +class _PeerSortDropdownState extends State { + @override + void initState() { + if (!PeerSortType.values.contains(peerSort.value)) { + peerSort.value = PeerSortType.remoteId; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: peerSort.value, + ); + } + super.initState(); + } + + @override + Widget build(BuildContext context) { + final deco = BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.circular(5), + ); + return Container( + padding: EdgeInsets.all(4.0), + decoration: deco, + child: DropdownButtonHideUnderline( + child: DropdownButton2( + onChanged: (v) async { + if (v != null) { + setState(() => peerSort.value = v); + await bind.setLocalFlutterConfig( + k: "peer-sorting", + v: peerSort.value, + ); + } + }, + customButton: Icon( + Icons.sort, + size: 18, + ), + dropdownStyleData: DropdownStyleData( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + ), + width: 160, + ), + items: [ + DropdownMenuItem( + alignment: Alignment.center, + child: Text( + translate("Sort by"), + style: TextStyle(fontWeight: FontWeight.bold), + ), + enabled: false, + ), + ...PeerSortType.values + .map>( + (String value) => DropdownMenuItem( + value: value, + child: Row( + children: [ + Icon( + value == peerSort.value + ? Icons.radio_button_checked_rounded + : Icons.radio_button_off_rounded, + size: 18, + ).paddingOnly(right: 12), + Text( + translate(value), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ) + .toList(), + ]), + ), + ); + } +} diff --git a/flutter/lib/common/widgets/peers_view.dart b/flutter/lib/common/widgets/peers_view.dart index 720e6727..197e5537 100644 --- a/flutter/lib/common/widgets/peers_view.dart +++ b/flutter/lib/common/widgets/peers_view.dart @@ -16,8 +16,31 @@ import 'peer_card.dart'; typedef PeerFilter = bool Function(Peer peer); typedef PeerCardBuilder = Widget Function(Peer peer); +class PeerSortType { + static const String remoteId = 'Remote ID'; + static const String remoteHost = 'Remote Host'; + static const String alias = 'Alias'; + static const String username = 'Username'; + static const String status = 'Status'; + + static List values = [ + PeerSortType.remoteId, + PeerSortType.remoteHost, + PeerSortType.alias, + PeerSortType.username, + PeerSortType.status + ]; +} + /// for peer search text, global obs value final peerSearchText = "".obs; + +/// for peer sort, global obs value +final peerSort = bind.getLocalFlutterConfig(k: 'peer-sorting').obs; + +// list for listener +final obslist = [peerSearchText, peerSort].obs; + final peerSearchTextController = TextEditingController(text: peerSearchText.value); @@ -114,7 +137,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { String _peerId(String cardId) => cardId.replaceAll(widget.peers.name, ''); Widget _buildPeersView(Peers peers) { - final body = ObxValue((searchText) { + final body = ObxValue((filters) { return FutureBuilder>( builder: (context, snapshot) { if (snapshot.hasData) { @@ -144,9 +167,9 @@ class _PeersViewState extends State<_PeersView> with WindowListener { ); } }, - future: matchPeers(searchText.value, peers.peers), + future: matchPeers(filters[0].value, filters[1].value, peers.peers), ); - }, peerSearchText); + }, obslist); return body; } @@ -185,11 +208,44 @@ class _PeersViewState extends State<_PeersView> with WindowListener { }(); } - Future>? matchPeers(String searchText, List peers) async { + Future>? matchPeers( + String searchText, String sortedBy, List peers) async { if (widget.peerFilter != null) { peers = peers.where((peer) => widget.peerFilter!(peer)).toList(); } + // fallback to id sorting + if (!PeerSortType.values.contains(sortedBy)) { + sortedBy = PeerSortType.remoteId; + bind.setLocalFlutterConfig( + k: "peer-sorting", + v: sortedBy, + ); + } + + if (widget.peers.loadEvent != 'load_recent_peers') { + switch (sortedBy) { + case PeerSortType.remoteId: + peers.sort((p1, p2) => p1.id.compareTo(p2.id)); + break; + case PeerSortType.remoteHost: + peers.sort((p1, p2) => + p1.hostname.toLowerCase().compareTo(p2.hostname.toLowerCase())); + break; + case PeerSortType.alias: + peers.sort((p1, p2) => + p1.alias.toLowerCase().compareTo(p2.alias.toLowerCase())); + break; + case PeerSortType.username: + peers.sort((p1, p2) => + p1.username.toLowerCase().compareTo(p2.username.toLowerCase())); + break; + case PeerSortType.status: + peers.sort((p1, p2) => p1.online ? -1 : 1); + break; + } + } + searchText = searchText.trim(); if (searchText.isEmpty) { return peers; @@ -203,6 +259,7 @@ class _PeersViewState extends State<_PeersView> with WindowListener { filteredList.add(peers[i]); } } + return filteredList; } } diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index 63f6c804..f3db9537 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -386,6 +386,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.2" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + sha256: "4458d81bfd24207f3d58f66f78097064e02f810f94cf1bc80bf20fe7685ebc80" + url: "https://pub.dev" + source: hosted + version: "2.0.0" event_bus: dependency: transitive description: diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 087fba71..46278bf0 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -94,6 +94,7 @@ dependencies: flutter_keyboard_visibility: ^5.4.0 texture_rgba_renderer: ^0.0.12 percent_indicator: ^4.2.2 + dropdown_button2: ^2.0.0 dev_dependencies: icons_launcher: ^2.0.4 diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 9507ffc2..a3c31c55 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index e5ba70aa..a32f35a5 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "安装虚拟显示器驱动,以便在没有连接显示器的情况下启动虚拟显示器进行控制。"), ("confirm_idd_driver_tip", "安装虚拟显示器驱动的选项已勾选。请注意,测试证书将被安装以信任虚拟显示器驱动。测试证书仅会用于信任Rustdesk的驱动。"), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 5920e002..50ea4e61 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 6e7394d7..c0d72221 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index f753265f..bdd82d47 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Installieren Sie den virtuellen Anzeigetreiber, der verwendet wird, wenn Sie keine physischen Anzeigen haben."), ("confirm_idd_driver_tip", "Die Option zur Installation des virtuellen Anzeigetreibers ist aktiviert. Beachten Sie, dass ein Testzertifikat installiert wird, um dem virtuellen Anzeigetreiber zu vertrauen. Dieses Testzertifikat wird nur verwendet, um Rustdesk-Treibern zu vertrauen."), ("RDP Settings", "RDP-Einstellungen"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index b0c8be87..6599e7a5 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Εγκαταστήστε το πρόγραμμα οδήγησης εικονικής οθόνης που χρησιμοποιείται όταν δεν έχετε φυσικές οθόνες."), ("confirm_idd_driver_tip", "Είναι ενεργοποιημένη η επιλογή εγκατάστασης του προγράμματος οδήγησης εικονικής οθόνης. Λάβετε υπόψη ότι θα εγκατασταθεί ένα δοκιμαστικό πιστοποιητικό για το πρόγραμμα οδήγησης εικονικής οθόνης. Αυτό το πιστοποιητικό θα χρησιμοποιηθεί μόνο για την πιστοποίηση των προγραμμάτων οδήγησης του Rustdesk."), ("RDP Settings", "Ρυθμίσεις RDP"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 457fbea0..7ccb8a8c 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 3543c515..85239cdd 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Instalar controlador virtual de pantalla a usar cuando no hay pantalla física."), ("confirm_idd_driver_tip", "La opción de instalar el controlador de pantalla virtual está marcada. Hay que tener en cuenta que se instalará un certificado de prueba para confirar en el controlador de pantalla. Este certificado solo se usará para confiar en controladores Rustdesk."), ("RDP Settings", "Ajustes RDP"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index f1503a83..a6459788 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 63d1ce31..887965b9 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 4789ba55..e64d972b 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index e2a969a8..ffba760e 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index dc59ccea..4d2da35f 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -208,7 +208,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("x11 expected", "x11 necessario"), ("Port", "Porta"), ("Settings", "Impostazioni"), - ("Username", " Nome utente"), + ("Username", "Nome utente"), ("Invalid port", "Numero di porta non valido"), ("Closed manually by the peer", "Chiuso manualmente dal peer"), ("Enable remote configuration modification", "Abilita la modifica remota della configurazione"), @@ -461,8 +461,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Resolution", "Risoluzione"), ("No transfers in progress", "Nessun trasferimento in corso"), ("Set one-time password length", "Imposta la lunghezza della password monouso"), - ("idd_driver_tip", ""), - ("confirm_idd_driver_tip", ""), + ("idd_driver_tip", "Installa il driver per lo schermo virtuale che sarà utilizzato quando non si dispone di schermi fisici."), + ("confirm_idd_driver_tip", "L'opzione per installare il driver per lo schermo virtuale è selezionata. Nota che un certificato di test sarà installato per l'attendibilità del driver dello schermo virtuale. Questo certificato di test verrà utilizzato solo per l'attendibilità dei driver di RustDesk."), ("RDP Settings", "Impostazioni RDP"), + ("Sort by", "Ordina per"), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index a2d3446b..9b7741d4 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 9c2076d6..ff6fdafb 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index b8a415e4..ca7c2d50 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 595e0710..a617ba2e 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 08f6ca90..0e8bbd31 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 1eb5fc6e..96a84de3 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index df0f5a26..f98e1116 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 7515ccbf..386f88c8 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index a1182843..dc714ec7 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", "Установите драйвер виртуального дисплея, который используется при отсутствии физических дисплеев."), ("confirm_idd_driver_tip", "Включена функция установки драйвера виртуального дисплея. Обратите внимание, что для доверия к драйверу будет установлен тестовый сертификат. Этот сертификат будет использоваться только для подтверждения доверия драйверам Rustdesk."), ("RDP Settings", "Настройки RDP"), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 1d8c6c62..38a3bd65 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 07bb2b54..41f4facb 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index a7cdfa8e..7e559287 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index bcdedef5..b2f5b62f 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 63167ed8..7a35df41 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 3fb6d17a..80e7f04e 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 808f69f8..f9bcf080 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 34949aa4..58a38e07 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 17ef4b7e..ff05d564 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index cc44d86d..04047ce9 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index b774e094..e38b06a5 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -464,5 +464,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("idd_driver_tip", ""), ("confirm_idd_driver_tip", ""), ("RDP Settings", ""), + ("Sort by", ""), ].iter().cloned().collect(); }