Merge branch 'master' into master

This commit is contained in:
yuluo
2024-04-23 03:03:45 +08:00
committed by GitHub
157 changed files with 6056 additions and 2087 deletions

View File

@@ -10,7 +10,7 @@ import './platform_model.dart';
import 'package:texture_rgba_renderer/texture_rgba_renderer.dart'
if (dart.library.html) 'package:flutter_hbb/web/texture_rgba_renderer.dart';
// Feature flutter_texture_render need to be enabled if feature gpucodec is enabled.
// Feature flutter_texture_render need to be enabled if feature vram is enabled.
final useTextureRender = !isWeb &&
(bind.mainHasPixelbufferTextureRender() || bind.mainHasGpuTextureRender());

View File

@@ -561,8 +561,12 @@ class FfiModel with ChangeNotifier {
showRelayHintDialog(sessionId, type, title, text, dialogManager, peerId);
} else if (text == 'Connected, waiting for image...') {
showConnectedWaitingForImage(dialogManager, sessionId, type, title, text);
} else if (title == 'Privacy mode') {
final hasRetry = evt['hasRetry'] == 'true';
showPrivacyFailedDialog(
sessionId, type, title, text, link, hasRetry, dialogManager);
} else {
var hasRetry = evt['hasRetry'] == 'true';
final hasRetry = evt['hasRetry'] == 'true';
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
}
}
@@ -657,6 +661,27 @@ class FfiModel with ChangeNotifier {
bind.sessionOnWaitingForImageDialogShow(sessionId: sessionId);
}
void showPrivacyFailedDialog(
SessionID sessionId,
String type,
String title,
String text,
String link,
bool hasRetry,
OverlayDialogManager dialogManager) {
if (text == 'no_need_privacy_mode_no_physical_displays_tip' ||
text == 'Enter privacy mode') {
// There are display changes on the remote side,
// which will cause some messages to refresh the canvas and dismiss dialogs.
// So we add a delay here to ensure the dialog is displayed.
Future.delayed(Duration(milliseconds: 3000), () {
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
});
} else {
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
}
}
_updateSessionWidthHeight(SessionID sessionId) {
if (_rect == null) return;
if (_rect!.width <= 0 || _rect!.height <= 0) {
@@ -690,6 +715,8 @@ class FfiModel with ChangeNotifier {
// Map clone is required here, otherwise "evt" may be changed by other threads through the reference.
// Because this function is asynchronous, there's an "await" in this function.
cachedPeerData.peerInfo = {...evt};
// Do not cache resolutions, because a new display connection have different resolutions.
cachedPeerData.peerInfo.remove('resolutions');
// Recent peer is updated by handle_peer_info(ui_session_interface.rs) --> handle_peer_info(client.rs) --> save_config(client.rs)
bind.mainLoadRecentPeers();
@@ -745,7 +772,9 @@ class FfiModel with ChangeNotifier {
}
Map<String, dynamic> features = json.decode(evt['features']);
_pi.features.privacyMode = features['privacy_mode'] == 1;
handleResolutions(peerId, evt["resolutions"]);
if (!isCache) {
handleResolutions(peerId, evt["resolutions"]);
}
parent.target?.elevationModel.onPeerInfo(_pi);
}
if (connType == ConnType.defaultConn) {
@@ -986,15 +1015,21 @@ class FfiModel with ChangeNotifier {
}
if (updateData.isEmpty) {
_pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays);
_pi.platformAdditions.remove(kPlatformAdditionsRustDeskVirtualDisplays);
_pi.platformAdditions.remove(kPlatformAdditionsAmyuniVirtualDisplays);
} else {
try {
final updateJson = json.decode(updateData) as Map<String, dynamic>;
for (final key in updateJson.keys) {
_pi.platformAdditions[key] = updateJson[key];
}
if (!updateJson.containsKey(kPlatformAdditionsVirtualDisplays)) {
_pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays);
if (!updateJson
.containsKey(kPlatformAdditionsRustDeskVirtualDisplays)) {
_pi.platformAdditions
.remove(kPlatformAdditionsRustDeskVirtualDisplays);
}
if (!updateJson.containsKey(kPlatformAdditionsAmyuniVirtualDisplays)) {
_pi.platformAdditions.remove(kPlatformAdditionsAmyuniVirtualDisplays);
}
} catch (e) {
debugPrint('Failed to decode platformAdditions $e');
@@ -2286,6 +2321,8 @@ class FFI {
}
await ffiModel.handleCachedPeerData(data, id);
await sessionRefreshVideo(sessionId, ffiModel.pi);
await bind.sessionRequestNewDisplayInitMsgs(
sessionId: sessionId, display: ffiModel.pi.currentDisplay);
});
isToNewWindowNotified.value = true;
}
@@ -2490,14 +2527,21 @@ class PeerInfo with ChangeNotifier {
bool get isInstalled =>
platform != kPeerPlatformWindows ||
platformAdditions[kPlatformAdditionsIsInstalled] == true;
List<int> get virtualDisplays => List<int>.from(
platformAdditions[kPlatformAdditionsVirtualDisplays] ?? []);
List<int> get RustDeskVirtualDisplays => List<int>.from(
platformAdditions[kPlatformAdditionsRustDeskVirtualDisplays] ?? []);
int get amyuniVirtualDisplayCount =>
platformAdditions[kPlatformAdditionsAmyuniVirtualDisplays] ?? 0;
bool get isSupportMultiDisplay =>
(isDesktop || isWebDesktop) && isSupportMultiUiSession;
bool get cursorEmbedded => tryGetDisplay()?.cursorEmbedded ?? false;
bool get isRustDeskIdd =>
platformAdditions[kPlatformAdditionsIddImpl] == 'rustdesk_idd';
bool get isAmyuniIdd =>
platformAdditions[kPlatformAdditionsIddImpl] == 'amyuni_idd';
Display? tryGetDisplay() {
if (displays.isEmpty) {
return null;

View File

@@ -198,7 +198,10 @@ class PlatformFFI {
await _ffiBind.mainDeviceId(id: id);
await _ffiBind.mainDeviceName(name: name);
await _ffiBind.mainSetHomeDir(home: _homeDir);
await _ffiBind.mainInit(appDir: _dir);
await _ffiBind.mainInit(
appDir: _dir,
customClientConfig: '',
);
} catch (e) {
debugPrintStack(label: 'initialize failed: $e');
}

View File

@@ -21,24 +21,43 @@ class PeerTabModel with ChangeNotifier {
WeakReference<FFI> parent;
int get currentTab => _currentTab;
int _currentTab = 0; // index in tabNames
List<String> tabNames = [
static const int maxTabCount = 5;
static const String kPeerTabIndex = 'peer-tab-index';
static const String kPeerTabOrder = 'peer-tab-order';
static const String kPeerTabVisible = 'peer-tab-visible';
static const List<String> tabNames = [
'Recent sessions',
'Favorites',
if (!isWeb) 'Discovered',
if (!(bind.isDisableAb() || bind.isDisableAccount())) 'Address book',
if (!bind.isDisableAccount()) 'Group',
'Discovered',
'Address book',
'Group',
];
final List<IconData> icons = [
static const List<IconData> icons = [
Icons.access_time_filled,
Icons.star,
if (!isWeb) Icons.explore,
if (!(bind.isDisableAb() || bind.isDisableAccount())) IconFont.addressBook,
if (!bind.isDisableAccount()) Icons.group,
Icons.explore,
IconFont.addressBook,
Icons.group,
];
final List<bool> _isVisible = List.filled(5, true, growable: false);
List<bool> get isVisible => _isVisible;
List<int> get indexs => List.generate(tabNames.length, (index) => index);
List<int> get visibleIndexs => indexs.where((e) => _isVisible[e]).toList();
List<bool> isEnabled = List.from([
true,
true,
!isWeb,
!(bind.isDisableAb() || bind.isDisableAccount()),
!bind.isDisableAccount(),
]);
final List<bool> _isVisible = List.filled(maxTabCount, true, growable: false);
List<bool> get isVisibleEnabled => () {
final list = _isVisible.toList();
for (int i = 0; i < maxTabCount; i++) {
list[i] = list[i] && isEnabled[i];
}
return list;
}();
final List<int> orders =
List.generate(maxTabCount, (index) => index, growable: false);
List<int> get visibleEnabledOrderedIndexs =>
orders.where((e) => isVisibleEnabled[e]).toList();
List<Peer> _selectedPeers = List.empty(growable: true);
List<Peer> get selectedPeers => _selectedPeers;
bool _multiSelectionMode = false;
@@ -53,7 +72,7 @@ class PeerTabModel with ChangeNotifier {
PeerTabModel(this.parent) {
// visible
try {
final option = bind.getLocalFlutterOption(k: 'peer-tab-visible');
final option = bind.getLocalFlutterOption(k: kPeerTabVisible);
if (option.isNotEmpty) {
List<dynamic> decodeList = jsonDecode(option);
if (decodeList.length == _isVisible.length) {
@@ -67,13 +86,37 @@ class PeerTabModel with ChangeNotifier {
} catch (e) {
debugPrint("failed to get peer tab visible list:$e");
}
// order
try {
final option = bind.getLocalFlutterOption(k: kPeerTabOrder);
if (option.isNotEmpty) {
List<dynamic> decodeList = jsonDecode(option);
if (decodeList.length == maxTabCount) {
var sortedList = decodeList.toList();
sortedList.sort();
bool valid = true;
for (int i = 0; i < maxTabCount; i++) {
if (sortedList[i] is! int || sortedList[i] != i) {
valid = false;
}
}
if (valid) {
for (int i = 0; i < orders.length; i++) {
orders[i] = decodeList[i];
}
}
}
}
} catch (e) {
debugPrint("failed to get peer tab order list: $e");
}
// init currentTab
_currentTab =
int.tryParse(bind.getLocalFlutterOption(k: 'peer-tab-index')) ?? 0;
if (_currentTab < 0 || _currentTab >= tabNames.length) {
int.tryParse(bind.getLocalFlutterOption(k: kPeerTabIndex)) ?? 0;
if (_currentTab < 0 || _currentTab >= maxTabCount) {
_currentTab = 0;
}
_trySetCurrentTabToFirstVisible();
_trySetCurrentTabToFirstVisibleEnabled();
}
setCurrentTab(int index) {
@@ -87,15 +130,13 @@ class PeerTabModel with ChangeNotifier {
if (index >= 0 && index < tabNames.length) {
return translate(tabNames[index]);
}
assert(false);
return index.toString();
}
IconData tabIcon(int index) {
if (index >= 0 && index < tabNames.length) {
if (index >= 0 && index < icons.length) {
return icons[index];
}
assert(false);
return Icons.help;
}
@@ -171,29 +212,54 @@ class PeerTabModel with ChangeNotifier {
}
setTabVisible(int index, bool visible) {
if (index >= 0 && index < _isVisible.length) {
if (index >= 0 && index < maxTabCount) {
if (_isVisible[index] != visible) {
_isVisible[index] = visible;
if (index == _currentTab && !visible) {
_trySetCurrentTabToFirstVisible();
} else if (visible && visibleIndexs.length == 1) {
_trySetCurrentTabToFirstVisibleEnabled();
} else if (visible && visibleEnabledOrderedIndexs.length == 1) {
_currentTab = index;
}
try {
bind.setLocalFlutterOption(
k: 'peer-tab-visible', v: jsonEncode(_isVisible));
k: kPeerTabVisible, v: jsonEncode(_isVisible));
} catch (_) {}
notifyListeners();
}
}
}
_trySetCurrentTabToFirstVisible() {
if (!_isVisible[_currentTab]) {
int firstVisible = _isVisible.indexWhere((e) => e);
if (firstVisible >= 0) {
_currentTab = firstVisible;
_trySetCurrentTabToFirstVisibleEnabled() {
if (!visibleEnabledOrderedIndexs.contains(_currentTab)) {
if (visibleEnabledOrderedIndexs.isNotEmpty) {
_currentTab = visibleEnabledOrderedIndexs.first;
}
}
}
reorder(int oldIndex, int newIndex) {
if (oldIndex < newIndex) {
newIndex -= 1;
}
if (oldIndex < 0 || oldIndex >= visibleEnabledOrderedIndexs.length) {
return;
}
if (newIndex < 0 || newIndex >= visibleEnabledOrderedIndexs.length) {
return;
}
final oldTabValue = visibleEnabledOrderedIndexs[oldIndex];
final newTabValue = visibleEnabledOrderedIndexs[newIndex];
int oldValueIndex = orders.indexOf(oldTabValue);
int newValueIndex = orders.indexOf(newTabValue);
final list = orders.toList();
if (oldIndex != -1 && newIndex != -1) {
list.removeAt(oldValueIndex);
list.insert(newValueIndex, oldTabValue);
for (int i = 0; i < list.length; i++) {
orders[i] = list[i];
}
bind.setLocalFlutterOption(k: kPeerTabOrder, v: jsonEncode(orders));
notifyListeners();
}
}
}