mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
add file log page to cm
* Only send and receive logs are shown * For older version, client send to server doesn't have size information, because server side doesn't know the total_size * Not switch tabs automatically when new files are transferred * If cm side page is open, not pop up automatically when new files are transferred * Show unread message count * The cm tab remains open when closed if a file transfer has previously occurred Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
@@ -86,13 +86,13 @@ class ChatModel with ChangeNotifier {
|
||||
late final Map<MessageKey, MessageBody> _messages = {};
|
||||
|
||||
MessageKey _currentKey = MessageKey('', -2); // -2 is invalid value
|
||||
late bool _isShowCMChatPage = false;
|
||||
late bool _isShowCMSidePage = false;
|
||||
|
||||
Map<MessageKey, MessageBody> get messages => _messages;
|
||||
|
||||
MessageKey get currentKey => _currentKey;
|
||||
|
||||
bool get isShowCMChatPage => _isShowCMChatPage;
|
||||
bool get isShowCMSidePage => _isShowCMSidePage;
|
||||
|
||||
void setOverlayState(BlockableOverlayState blockableOverlayState) {
|
||||
_blockableOverlayState = blockableOverlayState;
|
||||
@@ -255,7 +255,7 @@ class ChatModel with ChangeNotifier {
|
||||
showChatPage(MessageKey key) async {
|
||||
if (isDesktop) {
|
||||
if (isConnManager) {
|
||||
if (!_isShowCMChatPage) {
|
||||
if (!_isShowCMSidePage) {
|
||||
await toggleCMChatPage(key);
|
||||
}
|
||||
} else {
|
||||
@@ -272,12 +272,26 @@ class ChatModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
showSidePage() async {
|
||||
if (isDesktop) {
|
||||
if (isConnManager) {
|
||||
if (!_isShowCMSidePage) {
|
||||
await toggleCMSidePage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleCMChatPage(MessageKey key) async {
|
||||
if (gFFI.chatModel.currentKey != key) {
|
||||
gFFI.chatModel.changeCurrentKey(key);
|
||||
}
|
||||
if (_isShowCMChatPage) {
|
||||
_isShowCMChatPage = !_isShowCMChatPage;
|
||||
await toggleCMSidePage();
|
||||
}
|
||||
|
||||
toggleCMSidePage() async {
|
||||
if (_isShowCMSidePage) {
|
||||
_isShowCMSidePage = !_isShowCMSidePage;
|
||||
notifyListeners();
|
||||
await windowManager.show();
|
||||
await windowManager.setSizeAlignment(
|
||||
@@ -287,7 +301,7 @@ class ChatModel with ChangeNotifier {
|
||||
await windowManager.show();
|
||||
await windowManager.setSizeAlignment(
|
||||
kConnectionManagerWindowSizeOpenChat, Alignment.topRight);
|
||||
_isShowCMChatPage = !_isShowCMChatPage;
|
||||
_isShowCMSidePage = !_isShowCMSidePage;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
154
flutter/lib/models/cm_file_model.dart
Normal file
154
flutter/lib/models/cm_file_model.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:flutter_hbb/models/model.dart';
|
||||
import 'package:flutter_hbb/models/server_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'file_model.dart';
|
||||
|
||||
class CmFileModel {
|
||||
final WeakReference<FFI> parent;
|
||||
final currentJobTable = RxList<JobProgress>();
|
||||
final _jobTables = HashMap<int, RxList<JobProgress>>.fromEntries([]);
|
||||
Stopwatch stopwatch = Stopwatch();
|
||||
int _lastElapsed = 0;
|
||||
bool _jobAdded = false;
|
||||
bool _showing = false;
|
||||
|
||||
CmFileModel(this.parent);
|
||||
|
||||
void updateCurrentClientId(int id) {
|
||||
if (_jobTables[id] == null) {
|
||||
_jobTables[id] = RxList<JobProgress>();
|
||||
}
|
||||
Future.delayed(Duration.zero, () {
|
||||
currentJobTable.value = _jobTables[id]!;
|
||||
});
|
||||
}
|
||||
|
||||
onFileTransferLog(dynamic log) {
|
||||
try {
|
||||
dynamic d = jsonDecode(log);
|
||||
if (!stopwatch.isRunning) stopwatch.start();
|
||||
bool calcSpeed = stopwatch.elapsedMilliseconds - _lastElapsed >= 1000;
|
||||
if (calcSpeed) {
|
||||
_lastElapsed = stopwatch.elapsedMilliseconds;
|
||||
}
|
||||
if (d is List<dynamic>) {
|
||||
for (var l in d) {
|
||||
_dealOneJob(l, calcSpeed);
|
||||
}
|
||||
} else {
|
||||
_dealOneJob(d, calcSpeed);
|
||||
}
|
||||
currentJobTable.refresh();
|
||||
Future.delayed(Duration.zero, () async {
|
||||
if (_jobAdded) {
|
||||
_jobAdded = false;
|
||||
if (!_showing) {
|
||||
_showing = true;
|
||||
await gFFI.chatModel.showSidePage();
|
||||
_showing = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint("onFileTransferLog:$e");
|
||||
}
|
||||
}
|
||||
|
||||
_dealOneJob(dynamic l, bool calcSpeed) {
|
||||
final data = TransferJobSerdeData.fromJson(l);
|
||||
Client? client =
|
||||
gFFI.serverModel.clients.firstWhereOrNull((e) => e.id == data.connId);
|
||||
var jobTable = _jobTables[data.connId];
|
||||
if (jobTable == null) {
|
||||
debugPrint("jobTable should not be null");
|
||||
return;
|
||||
}
|
||||
JobProgress? job = jobTable.firstWhereOrNull((e) => e.id == data.id);
|
||||
if (job == null) {
|
||||
job = JobProgress();
|
||||
jobTable.add(job);
|
||||
_jobAdded = true;
|
||||
final currentSelectedTab =
|
||||
gFFI.serverModel.tabController.state.value.selectedTabInfo;
|
||||
if (currentSelectedTab.key != data.connId.toString()) {
|
||||
client?.unreadChatMessageCount.value += 1;
|
||||
}
|
||||
}
|
||||
job.id = data.id;
|
||||
job.isRemoteToLocal = data.isRemote;
|
||||
job.fileName = data.path;
|
||||
job.totalSize = data.totalSize;
|
||||
job.finishedSize = data.finishedSize;
|
||||
if (job.finishedSize > data.totalSize) {
|
||||
job.finishedSize = data.totalSize;
|
||||
}
|
||||
job.isRemoteToLocal = data.isRemote;
|
||||
|
||||
if (job.finishedSize > 0) {
|
||||
if (job.finishedSize < job.totalSize) {
|
||||
job.state = JobState.inProgress;
|
||||
} else {
|
||||
job.state = JobState.done;
|
||||
}
|
||||
}
|
||||
if (data.done) {
|
||||
job.state = JobState.done;
|
||||
} else if (data.cancel || data.error == 'skipped') {
|
||||
job.state = JobState.done;
|
||||
job.err = 'skipped';
|
||||
} else if (data.error.isNotEmpty) {
|
||||
job.state = JobState.error;
|
||||
job.err = data.error;
|
||||
}
|
||||
if (calcSpeed) {
|
||||
job.speed = (data.transferred - job.lastTransferredSize) * 1.0;
|
||||
job.lastTransferredSize = data.transferred;
|
||||
}
|
||||
jobTable.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
class TransferJobSerdeData {
|
||||
int connId;
|
||||
int id;
|
||||
String path;
|
||||
bool isRemote;
|
||||
int totalSize;
|
||||
int finishedSize;
|
||||
int transferred;
|
||||
bool done;
|
||||
bool cancel;
|
||||
String error;
|
||||
|
||||
TransferJobSerdeData({
|
||||
required this.connId,
|
||||
required this.id,
|
||||
required this.path,
|
||||
required this.isRemote,
|
||||
required this.totalSize,
|
||||
required this.finishedSize,
|
||||
required this.transferred,
|
||||
required this.done,
|
||||
required this.cancel,
|
||||
required this.error,
|
||||
});
|
||||
|
||||
TransferJobSerdeData.fromJson(dynamic d)
|
||||
: this(
|
||||
connId: d['connId'] ?? 0,
|
||||
id: int.tryParse(d['id'].toString()) ?? 0,
|
||||
path: d['path'] ?? '',
|
||||
isRemote: d['isRemote'] ?? false,
|
||||
totalSize: d['totalSize'] ?? 0,
|
||||
finishedSize: d['finishedSize'] ?? 0,
|
||||
transferred: d['transferred'] ?? 0,
|
||||
done: d['done'] ?? false,
|
||||
cancel: d['cancel'] ?? false,
|
||||
error: d['error'] ?? '',
|
||||
);
|
||||
}
|
||||
@@ -1029,6 +1029,7 @@ class JobProgress {
|
||||
var to = "";
|
||||
var showHidden = false;
|
||||
var err = "";
|
||||
int lastTransferredSize = 0;
|
||||
|
||||
clear() {
|
||||
state = JobState.none;
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/generated_bridge.dart';
|
||||
import 'package:flutter_hbb/models/ab_model.dart';
|
||||
import 'package:flutter_hbb/models/chat_model.dart';
|
||||
import 'package:flutter_hbb/models/cm_file_model.dart';
|
||||
import 'package:flutter_hbb/models/file_model.dart';
|
||||
import 'package:flutter_hbb/models/group_model.dart';
|
||||
import 'package:flutter_hbb/models/peer_tab_model.dart';
|
||||
@@ -317,6 +318,10 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (name == "cm_file_transfer_log") {
|
||||
if (isDesktop) {
|
||||
gFFI.cmFileModel.onFileTransferLog(evt['log']);
|
||||
}
|
||||
} else {
|
||||
debugPrint('Unknown event name: $name');
|
||||
}
|
||||
@@ -1696,6 +1701,7 @@ class FFI {
|
||||
late final RecordingModel recordingModel; // session
|
||||
late final InputModel inputModel; // session
|
||||
late final ElevationModel elevationModel; // session
|
||||
late final CmFileModel cmFileModel; // cm
|
||||
|
||||
FFI(SessionID? sId) {
|
||||
sessionId = sId ?? (isDesktop ? Uuid().v4obj() : _constSessionId);
|
||||
@@ -1714,6 +1720,7 @@ class FFI {
|
||||
recordingModel = RecordingModel(WeakReference(this));
|
||||
inputModel = InputModel(WeakReference(this));
|
||||
elevationModel = ElevationModel(WeakReference(this));
|
||||
cmFileModel = CmFileModel(WeakReference(this));
|
||||
}
|
||||
|
||||
/// Mobile reuse FFI
|
||||
|
||||
Reference in New Issue
Block a user