mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-12-15 20:45:52 +00:00
fix: update macos (#12578)
* fix: update macos 1. Use `ditto` instead of `cp -r`. 2. Add prompt for extracting dmg. Signed-off-by: fufesou <linlong1266@gmail.com> * fix: error to err Signed-off-by: fufesou <linlong1266@gmail.com> * Refact: Remove "Extracting" Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
@@ -7,7 +7,10 @@ import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
final _isExtracting = false.obs;
|
||||
|
||||
void handleUpdate(String releasePageUrl) {
|
||||
_isExtracting.value = false;
|
||||
String downloadUrl = releasePageUrl.replaceAll('tag', 'download');
|
||||
String version = downloadUrl.substring(downloadUrl.lastIndexOf('/') + 1);
|
||||
final String downloadFile =
|
||||
@@ -25,13 +28,14 @@ void handleUpdate(String releasePageUrl) {
|
||||
gFFI.dialogManager.dismissAll();
|
||||
gFFI.dialogManager.show((setState, close, context) {
|
||||
return CustomAlertDialog(
|
||||
title: Text(translate('Downloading {$appName}')),
|
||||
title: Obx(() => Text(translate(
|
||||
_isExtracting.isTrue ? 'Installing ...' : 'Downloading {$appName}'))),
|
||||
content:
|
||||
UpdateProgress(releasePageUrl, downloadUrl, downloadId, onCanceled)
|
||||
.marginSymmetric(horizontal: 8)
|
||||
.paddingOnly(top: 12),
|
||||
actions: [
|
||||
dialogButton(translate('Cancel'), onPressed: () async {
|
||||
if (_isExtracting.isFalse) dialogButton(translate('Cancel'), onPressed: () async {
|
||||
onCanceled.value();
|
||||
await bind.mainSetCommon(
|
||||
key: 'cancel-downloader', value: downloadId.value);
|
||||
@@ -71,6 +75,7 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
int _downloadedSize = 0;
|
||||
int _getDataFailedCount = 0;
|
||||
final String _eventKeyDownloadNewVersion = 'download-new-version';
|
||||
final String _eventKeyExtractUpdateDmg = 'extract-update-dmg';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -82,6 +87,11 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
_eventKeyDownloadNewVersion, handleDownloadNewVersion,
|
||||
replace: true);
|
||||
bind.mainSetCommon(key: 'download-new-version', value: widget.downloadUrl);
|
||||
if (isMacOS) {
|
||||
platformFFI.registerEventHandler(_eventKeyExtractUpdateDmg,
|
||||
_eventKeyExtractUpdateDmg, handleExtractUpdateDmg,
|
||||
replace: true);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -89,6 +99,10 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
cancelQueryTimer();
|
||||
platformFFI.unregisterEventHandler(
|
||||
_eventKeyDownloadNewVersion, _eventKeyDownloadNewVersion);
|
||||
if (isMacOS) {
|
||||
platformFFI.unregisterEventHandler(
|
||||
_eventKeyExtractUpdateDmg, _eventKeyExtractUpdateDmg);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -113,10 +127,13 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
}
|
||||
}
|
||||
|
||||
void _onError(String error) {
|
||||
// `isExtractDmg` is true when handling extract-update-dmg event.
|
||||
// It's a rare case that the dmg file is corrupted and cannot be extracted.
|
||||
void _onError(String error, {bool isExtractDmg = false}) {
|
||||
cancelQueryTimer();
|
||||
|
||||
debugPrint('Download new version error: $error');
|
||||
debugPrint(
|
||||
'${isExtractDmg ? "Extract" : "Download"} new version error: $error');
|
||||
final msgBoxType = 'custom-nocancel-nook-hasclose';
|
||||
final msgBoxTitle = 'Error';
|
||||
final msgBoxText = 'download-new-version-failed-tip';
|
||||
@@ -138,7 +155,7 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
|
||||
final List<Widget> buttons = [
|
||||
dialogButton('Download', onPressed: jumplink),
|
||||
dialogButton('Retry', onPressed: retry),
|
||||
if (!isExtractDmg) dialogButton('Retry', onPressed: retry),
|
||||
dialogButton('Close', onPressed: close),
|
||||
];
|
||||
dialogManager.dismissAll();
|
||||
@@ -194,6 +211,21 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
_onError('The download file size is 0.');
|
||||
} else {
|
||||
setState(() {});
|
||||
if (isMacOS) {
|
||||
bind.mainSetCommon(
|
||||
key: 'extract-update-dmg', value: widget.downloadUrl);
|
||||
_isExtracting.value = true;
|
||||
} else {
|
||||
updateMsgBox();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateMsgBox() {
|
||||
msgBox(
|
||||
gFFI.sessionId,
|
||||
'custom-nocancel',
|
||||
@@ -208,23 +240,23 @@ class UpdateProgressState extends State<UpdateProgress> {
|
||||
submitTimeout: 5,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> handleExtractUpdateDmg(Map<String, dynamic> evt) async {
|
||||
_isExtracting.value = false;
|
||||
if (evt.containsKey('err') && (evt['err'] as String).isNotEmpty) {
|
||||
_onError(evt['err'] as String, isExtractDmg: true);
|
||||
} else {
|
||||
setState(() {});
|
||||
}
|
||||
updateMsgBox();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return onDownloading(context);
|
||||
}
|
||||
|
||||
Widget onDownloading(BuildContext context) {
|
||||
final value = _totalSize == null
|
||||
getValue() => _totalSize == null
|
||||
? 0.0
|
||||
: (_totalSize == 0 ? 1.0 : _downloadedSize / _totalSize!);
|
||||
return LinearProgressIndicator(
|
||||
value: value,
|
||||
value: _isExtracting.isTrue ? null : getValue(),
|
||||
minHeight: 20,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
backgroundColor: Colors.grey[300],
|
||||
|
||||
@@ -629,7 +629,10 @@ pub fn session_open_terminal(session_id: SessionID, terminal_id: i32, rows: u32,
|
||||
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
|
||||
session.open_terminal(terminal_id, rows, cols);
|
||||
} else {
|
||||
log::error!("[flutter_ffi] Session not found for session_id: {}", session_id);
|
||||
log::error!(
|
||||
"[flutter_ffi] Session not found for session_id: {}",
|
||||
session_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2651,6 +2654,21 @@ pub fn main_set_common(_key: String, _value: String) {
|
||||
fs::remove_file(f).ok();
|
||||
}
|
||||
}
|
||||
} else if _key == "extract-update-dmg" {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if let Some(new_version_file) = get_download_file_from_url(&_value) {
|
||||
if let Some(f) = new_version_file.to_str() {
|
||||
crate::platform::macos::extract_update_dmg(f);
|
||||
} else {
|
||||
// unreachable!()
|
||||
log::error!("Failed to get the new version file path");
|
||||
}
|
||||
} else {
|
||||
// unreachable!()
|
||||
log::error!("Failed to get the new version file from url: {}", _value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use objc::rc::autoreleasepool;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use scrap::{libc::c_void, quartz::ffi::*};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
os::unix::process::CommandExt,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
@@ -743,7 +744,7 @@ pub fn update_me() -> ResultType<()> {
|
||||
let update_body = format!(
|
||||
r#"
|
||||
do shell script "
|
||||
pgrep -x 'RustDesk' | grep -v {} | xargs kill -9 && rm -rf /Applications/RustDesk.app && cp -R '{}' /Applications/ && chown -R {}:staff /Applications/RustDesk.app
|
||||
pgrep -x 'RustDesk' | grep -v {} | xargs kill -9 && rm -rf /Applications/RustDesk.app && ditto '{}' /Applications/RustDesk.app && chown -R {}:staff /Applications/RustDesk.app && xattr -r -d com.apple.quarantine /Applications/RustDesk.app
|
||||
" with prompt "RustDesk wants to update itself" with administrator privileges
|
||||
"#,
|
||||
std::process::id(),
|
||||
@@ -775,11 +776,26 @@ pgrep -x 'RustDesk' | grep -v {} | xargs kill -9 && rm -rf /Applications/RustDes
|
||||
}
|
||||
|
||||
pub fn update_to(file: &str) -> ResultType<()> {
|
||||
extract_dmg(file, UPDATE_TEMP_DIR)?;
|
||||
update_extracted(UPDATE_TEMP_DIR)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn extract_update_dmg(file: &str) {
|
||||
let mut evt: HashMap<&str, String> =
|
||||
HashMap::from([("name", "extract-update-dmg".to_string())]);
|
||||
match extract_dmg(file, UPDATE_TEMP_DIR) {
|
||||
Ok(_) => {
|
||||
log::info!("Extracted dmg file to {}", UPDATE_TEMP_DIR);
|
||||
}
|
||||
Err(e) => {
|
||||
evt.insert("err", e.to_string());
|
||||
log::error!("Failed to extract dmg file {}: {}", file, e);
|
||||
}
|
||||
}
|
||||
let evt = serde_json::ser::to_string(&evt).unwrap_or("".to_owned());
|
||||
crate::flutter::push_global_event(crate::flutter::APP_TYPE_MAIN, evt);
|
||||
}
|
||||
|
||||
fn extract_dmg(dmg_path: &str, target_dir: &str) -> ResultType<()> {
|
||||
let mount_point = "/Volumes/RustDeskUpdate";
|
||||
let target_path = Path::new(target_dir);
|
||||
@@ -807,8 +823,8 @@ fn extract_dmg(dmg_path: &str, target_dir: &str) -> ResultType<()> {
|
||||
let src_path = format!("{}/{}", mount_point, app_name);
|
||||
let dest_path = format!("{}/{}", target_dir, app_name);
|
||||
|
||||
let copy_status = Command::new("cp")
|
||||
.args(&["-R", &src_path, &dest_path])
|
||||
let copy_status = Command::new("ditto")
|
||||
.args(&[&src_path, &dest_path])
|
||||
.status()?;
|
||||
|
||||
if !copy_status.success() {
|
||||
|
||||
@@ -4,7 +4,7 @@ on run {daemon_file, agent_file, user, cur_pid, source_dir}
|
||||
|
||||
set kill_others to "pgrep -x 'RustDesk' | grep -v " & cur_pid & " | xargs kill -9;"
|
||||
|
||||
set copy_files to "rm -rf /Applications/RustDesk.app && cp -r " & source_dir & " /Applications && chown -R " & quoted form of user & ":staff /Applications/RustDesk.app;"
|
||||
set copy_files to "rm -rf /Applications/RustDesk.app && ditto " & source_dir & " /Applications/RustDesk.app && chown -R " & quoted form of user & ":staff /Applications/RustDesk.app && xattr -r -d com.apple.quarantine /Applications/RustDesk.app;"
|
||||
|
||||
set sh1 to "echo " & quoted form of daemon_file & " > /Library/LaunchDaemons/com.carriez.RustDesk_service.plist && chown root:wheel /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user