Compare commits

...

7 Commits

Author SHA1 Message Date
fufesou 58ee593e26 fix(custom-client): show options, incoming-only (#15394)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-06-24 00:26:09 +08:00
fufesou 09bc9056c9 fix(update): win aarch64 (#15389)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-06-23 17:59:29 +08:00
fufesou 0c6df924d1 refact: file transfer, do this for all conflicts(tasks) (#15385)
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-06-23 11:23:42 +08:00
dependabot[bot] 456817b4f4 Git submodule: bump libs/hbb_common from e50ac3c to 387603f (#15384)
Bumps [libs/hbb_common](https://github.com/rustdesk/hbb_common) from `e50ac3c` to `387603f`.
- [Release notes](https://github.com/rustdesk/hbb_common/releases)
- [Commits](https://github.com/rustdesk/hbb_common/compare/e50ac3cd4897fa6c6ed545189adb2170c34df636...387603f47cbb15c0d3dc3d67ae3396d3eb707daf)

---
updated-dependencies:
- dependency-name: libs/hbb_common
  dependency-version: 387603f47cbb15c0d3dc3d67ae3396d3eb707daf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-23 10:28:08 +08:00
rustdesk 16570ee34f fix https://github.com/rustdesk/rustdesk/discussions/15355 2026-06-22 22:57:08 +08:00
just-some-tall-bloke 2b40c61d8e Fix spelling and grammar errors in comments (#15370)
- dbus.rs: fix grammar (add 'between', pluralize 'processes')
- win_impl.rs: fix typo 'hight' -> 'high', idiom 'such called' -> 'so-called'
- startwm.sh: fix typo 'loging' -> 'logging'
- lib.rs: fix copy-paste error in doc comments for scroll buttons
- message.proto: fix typo 'Clipobard' -> 'Clipboard'
2026-06-22 15:26:51 +08:00
RustDesk dcc64cdeae cjk (#15379) 2026-06-22 14:47:12 +08:00
63 changed files with 481 additions and 89 deletions
@@ -483,13 +483,15 @@ class _GeneralState extends State<_General> {
} }
Widget other() { Widget other() {
final incomingOnly = bind.isIncomingOnly();
final outgoingOnly = bind.isOutgoingOnly();
final showAutoUpdate = isWindows && bind.mainIsInstalled(); final showAutoUpdate = isWindows && bind.mainIsInstalled();
final children = <Widget>[ final children = <Widget>[
if (!isWeb && !bind.isIncomingOnly()) if (!isWeb && !incomingOnly)
_OptionCheckBox(context, 'Confirm before closing multiple tabs', _OptionCheckBox(context, 'Confirm before closing multiple tabs',
kOptionEnableConfirmClosingTabs, kOptionEnableConfirmClosingTabs,
isServer: false), isServer: false),
if (!bind.isIncomingOnly()) if (!incomingOnly)
_OptionCheckBox( _OptionCheckBox(
context, context,
'allow-remote-toolbar-docking-any-edge', 'allow-remote-toolbar-docking-any-edge',
@@ -499,9 +501,10 @@ class _GeneralState extends State<_General> {
reloadAllWindows(); reloadAllWindows();
}, },
), ),
if (!isWeb && !outgoingOnly)
_OptionCheckBox(context, 'Adaptive bitrate', kOptionEnableAbr), _OptionCheckBox(context, 'Adaptive bitrate', kOptionEnableAbr),
if (!isWeb) wallpaper(), if (!isWeb) wallpaper(),
if (!isWeb && !bind.isIncomingOnly()) ...[ if (!isWeb && !incomingOnly) ...[
_OptionCheckBox( _OptionCheckBox(
context, context,
'Open connection in new tab', 'Open connection in new tab',
@@ -540,6 +543,7 @@ class _GeneralState extends State<_General> {
isServer: false, isServer: false,
), ),
), ),
],
if (!isWeb && !bind.isCustomClient()) if (!isWeb && !bind.isCustomClient())
_OptionCheckBox( _OptionCheckBox(
context, context,
@@ -554,13 +558,13 @@ class _GeneralState extends State<_General> {
kOptionAllowAutoUpdate, kOptionAllowAutoUpdate,
isServer: true, isServer: true,
), ),
if (isWindows && !bind.isOutgoingOnly()) if (isWindows && !outgoingOnly)
_OptionCheckBox( _OptionCheckBox(
context, context,
'Capture screen using DirectX', 'Capture screen using DirectX',
kOptionDirectxCapture, kOptionDirectxCapture,
), ),
if (!bind.isIncomingOnly()) ...[ if (!isWeb && !incomingOnly) ...[
_OptionCheckBox( _OptionCheckBox(
context, context,
'Enable UDP hole punching', 'Enable UDP hole punching',
@@ -574,7 +578,6 @@ class _GeneralState extends State<_General> {
isServer: false, isServer: false,
), ),
], ],
],
]; ];
// Add client-side wakelock option for desktop platforms // Add client-side wakelock option for desktop platforms
@@ -1167,8 +1167,8 @@ class _MonitorMenu extends StatelessWidget {
tooltip: isMulti tooltip: isMulti
? '' ? ''
: isAllMonitors : isAllMonitors
? 'all monitors' ? 'All monitors'
: '#${i + 1} monitor', : '#{${i + 1}} monitor',
hMargin: isMulti ? null : 6, hMargin: isMulti ? null : 6,
vMargin: isMulti ? null : 12, vMargin: isMulti ? null : 12,
topLevel: false, topLevel: false,
@@ -2852,7 +2852,7 @@ class _IconMenuButtonState extends State<_IconMenuButton> {
horizontal: widget.hMargin ?? _ToolbarTheme.buttonHMargin, horizontal: widget.hMargin ?? _ToolbarTheme.buttonHMargin,
vertical: widget.vMargin ?? _ToolbarTheme.buttonVMargin); vertical: widget.vMargin ?? _ToolbarTheme.buttonVMargin);
button = Tooltip( button = Tooltip(
message: widget.tooltip, message: translate(widget.tooltip),
child: button, child: button,
); );
if (widget.topLevel) { if (widget.topLevel) {
+164 -13
View File
@@ -142,12 +142,22 @@ class FileModel {
} }
Future<void> postOverrideFileConfirm(Map<String, dynamic> evt) async { Future<void> postOverrideFileConfirm(Map<String, dynamic> evt) async {
final id = int.tryParse(evt['id']?.toString() ?? '');
if (id == null || !jobController.hasTransferConflictJob(id)) {
debugPrint("Ignore stale override confirm event: $evt");
return;
}
evtLoop.pushEvent( evtLoop.pushEvent(
_FileDialogEvent(WeakReference(this), FileDialogType.overwrite, evt)); _FileDialogEvent(WeakReference(this), FileDialogType.overwrite, evt));
} }
Future<void> overrideFileConfirm(Map<String, dynamic> evt, Future<void> overrideFileConfirm(Map<String, dynamic> evt,
{bool? overrideConfirm, bool skip = false}) async { {bool? overrideConfirm, bool skip = false}) async {
final id = int.tryParse(evt['id']?.toString() ?? '') ?? 0;
if (id == 0 || !jobController.hasTransferConflictJob(id)) {
debugPrint("Ignore override confirm for inactive job: $evt");
return;
}
// If `skip == true`, it means to skip this file without showing dialog. // If `skip == true`, it means to skip this file without showing dialog.
// Because `resp` may be null after the user operation or the last remembered operation, // Because `resp` may be null after the user operation or the last remembered operation,
// and we should distinguish them. // and we should distinguish them.
@@ -156,15 +166,12 @@ class FileModel {
? await showFileConfirmDialog(translate("Overwrite"), ? await showFileConfirmDialog(translate("Overwrite"),
"${evt['read_path']}", true, evt['is_identical'] == "true") "${evt['read_path']}", true, evt['is_identical'] == "true")
: null); : null);
final id = int.tryParse(evt['id']) ?? 0; if (!jobController.hasTransferConflictJob(id)) {
if (false == resp) { debugPrint("Ignore override confirm result for inactive job: $evt");
final jobIndex = jobController.getJob(id); return;
if (jobIndex != -1) {
await jobController.cancelJob(id);
final job = jobController.jobTable[jobIndex];
job.state = JobState.done;
jobController.jobTable.refresh();
} }
if (false == resp) {
await jobController.cancelTransferConflictBatch(id);
} else { } else {
var need_override = false; var need_override = false;
if (resp == null) { if (resp == null) {
@@ -176,6 +183,7 @@ class FileModel {
} }
// Update the loop config. // Update the loop config.
if (fileConfirmCheckboxRemember) { if (fileConfirmCheckboxRemember) {
jobController.rememberTransferConflictBatch(id, resp);
evtLoop.setSkip(!need_override); evtLoop.setSkip(!need_override);
} }
await bind.sessionSetConfirmOverrideFile( await bind.sessionSetConfirmOverrideFile(
@@ -285,6 +293,8 @@ class FileModel {
final isWindows = otherSideData.options.isWindows; final isWindows = otherSideData.options.isWindows;
final showHidden = otherSideData.options.showHidden; final showHidden = otherSideData.options.showHidden;
final jobID = jobController.addTransferJob(entry, false); final jobID = jobController.addTransferJob(entry, false);
jobController.registerTransferConflictBatch([jobID],
batchId: int.tryParse(obj['batchId']?.toString() ?? ''));
webSendLocalFiles( webSendLocalFiles(
handleIndex: handleIndex, handleIndex: handleIndex,
actId: jobID, actId: jobID,
@@ -570,8 +580,15 @@ class FileController {
final toPath = otherSideData.directory.path; final toPath = otherSideData.directory.path;
final isWindows = otherSideData.options.isWindows; final isWindows = otherSideData.options.isWindows;
final showHidden = otherSideData.options.showHidden; final showHidden = otherSideData.options.showHidden;
final transferJobs = <(Entry, int)>[];
final transferJobIds = <int>[];
for (var from in items.items) { for (var from in items.items) {
final jobID = jobController.addTransferJob(from, isRemoteToLocal); final jobID = jobController.addTransferJob(from, isRemoteToLocal);
transferJobs.add((from, jobID));
transferJobIds.add(jobID);
}
jobController.registerTransferConflictBatch(transferJobIds);
for (final (from, jobID) in transferJobs) {
bind.sessionSendFiles( bind.sessionSendFiles(
sessionId: sessionId, sessionId: sessionId,
actId: jobID, actId: jobID,
@@ -917,6 +934,10 @@ class JobController {
static final JobID jobID = JobID(); static final JobID jobID = JobID();
final jobTable = List<JobProgress>.empty(growable: true).obs; final jobTable = List<JobProgress>.empty(growable: true).obs;
final jobResultListener = JobResultListener<Map<String, dynamic>>(); final jobResultListener = JobResultListener<Map<String, dynamic>>();
int _nextTransferConflictBatchId = 1;
final Map<int, int> _transferConflictJobToBatch = {};
int? _transferConflictRememberBatchId;
bool? _transferConflictRememberOverrideConfirm;
final GetSessionID getSessionID; final GetSessionID getSessionID;
final GetDialogManager getDialogManager; final GetDialogManager getDialogManager;
SessionID get sessionId => getSessionID(); SessionID get sessionId => getSessionID();
@@ -929,6 +950,57 @@ class JobController {
return jobTable.indexWhere((element) => element.id == id); return jobTable.indexWhere((element) => element.id == id);
} }
void registerTransferConflictBatch(Iterable<int> jobIds, {int? batchId}) {
final ids = jobIds.toList(growable: false);
if (ids.isEmpty) {
return;
}
batchId ??= _nextTransferConflictBatchId++;
if (batchId >= _nextTransferConflictBatchId) {
_nextTransferConflictBatchId = batchId + 1;
}
for (final jobId in ids) {
_transferConflictJobToBatch[jobId] = batchId;
}
}
int? transferConflictBatchId(int jobId) {
return _transferConflictJobToBatch[jobId];
}
bool hasTransferConflictJob(int jobId) {
return transferConflictBatchId(jobId) != null;
}
bool isTransferConflictRememberBatch(int? batchId) {
return batchId != null && batchId == _transferConflictRememberBatchId;
}
bool? transferConflictRememberOverrideConfirm(int? batchId) {
if (!isTransferConflictRememberBatch(batchId)) {
return null;
}
return _transferConflictRememberOverrideConfirm;
}
void rememberTransferConflictBatch(int jobId, bool? overrideConfirm) {
_transferConflictRememberBatchId = _transferConflictJobToBatch[jobId];
_transferConflictRememberOverrideConfirm = overrideConfirm;
}
void unregisterTransferConflictJob(int jobId) {
final batchId = _transferConflictJobToBatch.remove(jobId);
if (batchId == null) {
return;
}
if (!_transferConflictJobToBatch.containsValue(batchId)) {
if (_transferConflictRememberBatchId == batchId) {
_transferConflictRememberBatchId = null;
_transferConflictRememberOverrideConfirm = null;
}
}
}
// return jobID // return jobID
int addTransferJob(Entry from, bool isRemoteToLocal) { int addTransferJob(Entry from, bool isRemoteToLocal) {
final jobID = JobController.jobID.next(); final jobID = JobController.jobID.next();
@@ -1000,7 +1072,10 @@ class JobController {
id = int.parse(evt['id']); id = int.parse(evt['id']);
} catch (_) {} } catch (_) {}
final jobIndex = getJob(id); final jobIndex = getJob(id);
if (jobIndex == -1) return true; if (jobIndex == -1) {
unregisterTransferConflictJob(id);
return true;
}
final job = jobTable[jobIndex]; final job = jobTable[jobIndex];
job.recvJobRes = true; job.recvJobRes = true;
if (job.type == JobType.deleteFile) { if (job.type == JobType.deleteFile) {
@@ -1026,6 +1101,9 @@ class JobController {
job.state = JobState.done; job.state = JobState.done;
} }
jobTable.refresh(); jobTable.refresh();
if (job.state == JobState.done || job.state == JobState.error) {
unregisterTransferConflictJob(id);
}
if (job.type == JobType.deleteDir) { if (job.type == JobType.deleteDir) {
return job.state == JobState.done; return job.state == JobState.done;
} else { } else {
@@ -1035,9 +1113,15 @@ class JobController {
void jobError(Map<String, dynamic> evt) { void jobError(Map<String, dynamic> evt) {
final err = evt['err'].toString(); final err = evt['err'].toString();
int jobIndex = getJob(int.parse(evt['id'])); final id = int.tryParse(evt['id']?.toString() ?? '');
if (id == null) {
debugPrint("Ignore job error with invalid id: $evt");
return;
}
int jobIndex = getJob(id);
if (jobIndex != -1) { if (jobIndex != -1) {
final job = jobTable[jobIndex]; final job = jobTable[jobIndex];
if (job.state == JobState.done && job.err == "cancel") return;
job.state = JobState.error; job.state = JobState.error;
job.err = err; job.err = err;
job.recvJobRes = true; job.recvJobRes = true;
@@ -1060,6 +1144,11 @@ class JobController {
} }
} }
jobTable.refresh(); jobTable.refresh();
if (job.state == JobState.done || job.state == JobState.error) {
unregisterTransferConflictJob(job.id);
}
} else {
unregisterTransferConflictJob(id);
} }
if (err == _kOneWayFileTransferError) { if (err == _kOneWayFileTransferError) {
if (DateTime.now().millisecondsSinceEpoch - _lastTimeShowMsgbox > 3000) { if (DateTime.now().millisecondsSinceEpoch - _lastTimeShowMsgbox > 3000) {
@@ -1096,9 +1185,42 @@ class JobController {
} }
Future<void> cancelJob(int id) async { Future<void> cancelJob(int id) async {
unregisterTransferConflictJob(id);
await bind.sessionCancelJob(sessionId: sessionId, actId: id); await bind.sessionCancelJob(sessionId: sessionId, actId: id);
} }
Future<void> cancelTransferConflictBatch(int jobId) async {
final batchId = _transferConflictJobToBatch[jobId];
final batchJobIds = batchId == null ? [jobId] : <int>[];
if (batchId != null) {
for (final entry in _transferConflictJobToBatch.entries) {
if (entry.value == batchId) {
batchJobIds.add(entry.key);
}
}
for (final id in batchJobIds) {
unregisterTransferConflictJob(id);
}
}
final jobIdsToCancel = batchJobIds.toSet();
for (final job in jobTable) {
if (!jobIdsToCancel.contains(job.id) || job.state == JobState.done) {
continue;
}
job.state = JobState.done;
job.err = "cancel";
job.recvJobRes = true;
}
jobTable.refresh();
for (final id in batchJobIds) {
try {
await bind.sessionCancelJob(sessionId: sessionId, actId: id);
} catch (e) {
debugPrint("Failed to cancel transfer job $id in conflict batch: $e");
}
}
}
Future<void> loadLastJob(Map<String, dynamic> evt) async { Future<void> loadLastJob(Map<String, dynamic> evt) async {
debugPrint("load last job: $evt"); debugPrint("load last job: $evt");
Map<String, dynamic> jobDetail = json.decode(evt['value']); Map<String, dynamic> jobDetail = json.decode(evt['value']);
@@ -1145,7 +1267,7 @@ class JobController {
..state = JobState.paused; ..state = JobState.paused;
jobTable.add(jobProgress); jobTable.add(jobProgress);
} }
registerTransferConflictBatch([currJobId]);
await bind.sessionAddJob( await bind.sessionAddJob(
sessionId: sessionId, sessionId: sessionId,
isRemote: isRemote, isRemote: isRemote,
@@ -1193,6 +1315,9 @@ class JobController {
void clear() { void clear() {
jobTable.clear(); jobTable.clear();
_transferConflictJobToBatch.clear();
_transferConflictRememberBatchId = null;
_transferConflictRememberOverrideConfirm = null;
jobResultListener.clear(); jobResultListener.clear();
} }
} }
@@ -1535,6 +1660,9 @@ class JobProgress {
String display() { String display() {
if (type == JobType.transfer) { if (type == JobType.transfer) {
if (state == JobState.done && err == "cancel") {
return translate("Cancel");
}
if (state == JobState.done && err == "skipped") { if (state == JobState.done && err == "skipped") {
return translate("Skipped"); return translate("Skipped");
} }
@@ -1844,21 +1972,44 @@ class _FileDialogEvent extends BaseEvent<FileDialogType, Map<String, dynamic>> {
class FileDialogEventLoop class FileDialogEventLoop
extends BaseEventLoop<FileDialogType, Map<String, dynamic>> { extends BaseEventLoop<FileDialogType, Map<String, dynamic>> {
int? _batchId;
bool? _overrideConfirm; bool? _overrideConfirm;
bool _skip = false; bool _skip = false;
@override @override
Future<void> onPreConsume( Future<void> onPreConsume(
BaseEvent<FileDialogType, Map<String, dynamic>> evt) async { BaseEvent<FileDialogType, Map<String, dynamic>> evt) async {
var event = evt as _FileDialogEvent; final event = evt as _FileDialogEvent;
final model = event.fileModel.target;
final jobId = int.tryParse(evt.data['id']?.toString() ?? '');
final batchId = model == null || jobId == null
? null
: model.jobController.transferConflictBatchId(jobId);
final keepRemembered = model != null &&
model.jobController.isTransferConflictRememberBatch(batchId);
// The loop only preloads the remembered batch choice. The model updates it
// after the user answers the current overwrite dialog.
if (_batchId != batchId && !keepRemembered) {
_batchId = batchId;
_overrideConfirm = null;
_skip = false;
} else {
_batchId = batchId;
}
if (keepRemembered) {
_overrideConfirm =
model.jobController.transferConflictRememberOverrideConfirm(batchId);
_skip = _overrideConfirm == null;
}
event.setOverrideConfirm(_overrideConfirm); event.setOverrideConfirm(_overrideConfirm);
event.setSkip(_skip); event.setSkip(_skip);
debugPrint( debugPrint(
"FileDialogEventLoop: consuming<jobId: ${evt.data['id']} overrideConfirm: $_overrideConfirm, skip: $_skip>"); "FileDialogEventLoop: consuming<jobId: ${evt.data['id']} batchId: $_batchId overrideConfirm: $_overrideConfirm, skip: $_skip>");
} }
@override @override
Future<void> onEventsClear() { Future<void> onEventsClear() {
_batchId = null;
_overrideConfirm = null; _overrideConfirm = null;
_skip = false; _skip = false;
return super.onEventsClear(); return super.onEventsClear();
+3 -3
View File
@@ -113,11 +113,11 @@ pub enum MouseButton {
/// Scroll up button /// Scroll up button
ScrollUp, ScrollUp,
/// Left right button /// Scroll down button
ScrollDown, ScrollDown,
/// Left right button /// Scroll left button
ScrollLeft, ScrollLeft,
/// Left right button /// Scroll right button
ScrollRight, ScrollRight,
} }
+1 -1
View File
@@ -223,7 +223,7 @@ impl KeyboardControllable for Enigo {
// Windows uses uft-16 encoding. We need to check // Windows uses uft-16 encoding. We need to check
// for variable length characters. As such some // for variable length characters. As such some
// characters can be 32 bit long and those are // characters can be 32 bit long and those are
// encoded in such called hight and low surrogates // encoded in so-called high and low surrogates
// each 16 bit wide that needs to be send after // each 16 bit wide that needs to be send after
// another to the SendInput function without // another to the SendInput function without
// being interrupted by "keyup" // being interrupted by "keyup"
+1 -1
View File
@@ -45,7 +45,7 @@ pre_start()
return 0 return 0
} }
# When loging out from the interactive shell, the execution sequence is: # When logging out from the interactive shell, the execution sequence is:
# #
# IF ~/.bash_logout exists THEN # IF ~/.bash_logout exists THEN
# execute ~/.bash_logout # execute ~/.bash_logout
+10 -2
View File
@@ -2852,8 +2852,16 @@ pub fn main_get_common(key: String) -> String {
crate::platform::windows::is_msi_installed(), crate::platform::windows::is_msi_installed(),
crate::common::is_custom_client(), crate::common::is_custom_client(),
) { ) {
(Ok(true), false) => format!("rustdesk-{_version}-x86_64.msi"), (Ok(true), false) => match crate::platform::windows::release_arch_suffix() {
(Ok(true), true) | (Ok(false), _) => format!("rustdesk-{_version}-x86_64.exe"), Some(arch) => format!("rustdesk-{_version}-{arch}.msi"),
None => "error:unsupported".to_owned(),
},
(Ok(true), true) | (Ok(false), _) => {
match crate::platform::windows::release_arch_suffix() {
Some(arch) => format!("rustdesk-{_version}-{arch}.exe"),
None => "error:unsupported".to_owned(),
}
}
(Err(e), _) => { (Err(e), _) => {
log::error!("Failed to check if is msi: {}", e); log::error!("Failed to check if is msi: {}", e);
format!("error:update-failed-check-msi-tip") format!("error:update-failed-check-msi-tip")
+67 -7
View File
@@ -103,15 +103,29 @@ pub const LANGS: &[(&str, &str)] = &[
("gu", "ગુજરાતી"), ("gu", "ગુજરાતી"),
]; ];
#[cfg(not(any(target_os = "android", target_os = "ios")))] pub(crate) fn cjk_ui_unavailable() -> bool {
pub fn translate(name: String) -> String { cfg!(all(
let locale = sys_locale::get_locale().unwrap_or_default(); target_os = "linux",
translate_locale(name, &locale) target_arch = "aarch64",
feature = "flutter"
))
} }
pub fn translate_locale(name: String, locale: &str) -> String { pub(crate) fn is_cjk_lang(lang_or_locale: &str) -> bool {
let lang = lang_or_locale
.split(|c| c == '-' || c == '_')
.next()
.unwrap_or_default()
.to_lowercase();
matches!(lang.as_str(), "zh" | "ja" | "ko")
}
fn resolve_lang(saved_lang: &str, locale: &str, cjk_fallback: bool) -> String {
let locale = locale.to_lowercase(); let locale = locale.to_lowercase();
let mut lang = hbb_common::config::LocalConfig::get_option("lang").to_lowercase(); let mut lang = saved_lang.to_lowercase();
if cjk_fallback && is_cjk_lang(&lang) {
return "en".to_owned();
}
if lang.is_empty() { if lang.is_empty() {
// zh_CN on Linux, zh-Hans-CN on mac, zh_CN_#Hans on Android // zh_CN on Linux, zh-Hans-CN on mac, zh_CN_#Hans on Android
if locale.starts_with("zh") { if locale.starts_with("zh") {
@@ -131,7 +145,25 @@ pub fn translate_locale(name: String, locale: &str) -> String {
.unwrap_or_default() .unwrap_or_default()
.to_owned(); .to_owned();
} }
let lang = lang.to_lowercase(); if cjk_fallback && is_cjk_lang(&lang) {
"en".to_owned()
} else {
lang
}
}
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn translate(name: String) -> String {
let locale = sys_locale::get_locale().unwrap_or_default();
translate_locale(name, &locale)
}
pub fn translate_locale(name: String, locale: &str) -> String {
let lang = resolve_lang(
&hbb_common::config::LocalConfig::get_option("lang"),
locale,
cjk_ui_unavailable(),
);
let m = match lang.as_str() { let m = match lang.as_str() {
"fr" => fr::T.deref(), "fr" => fr::T.deref(),
"zh-cn" => cn::T.deref(), "zh-cn" => cn::T.deref(),
@@ -275,4 +307,32 @@ mod test {
("{} times {4} makes {8}".to_string(), Some("2".to_string())) ("{} times {4} makes {8}".to_string(), Some("2".to_string()))
); );
} }
#[test]
fn test_resolve_lang_forces_english_for_saved_cjk_when_target_disables_cjk() {
use super::resolve_lang as f;
assert_eq!(f("zh-cn", "en-US", true), "en");
assert_eq!(f("zh-tw", "en-US", true), "en");
assert_eq!(f("ja", "en-US", true), "en");
assert_eq!(f("ko", "en-US", true), "en");
}
#[test]
fn test_resolve_lang_forces_english_for_cjk_locale_when_target_disables_cjk() {
use super::resolve_lang as f;
assert_eq!(f("", "zh_CN", true), "en");
assert_eq!(f("", "ja-JP", true), "en");
assert_eq!(f("", "ko_KR", true), "en");
}
#[test]
fn test_resolve_lang_preserves_cjk_when_target_allows_cjk() {
use super::resolve_lang as f;
assert_eq!(f("zh-cn", "en-US", false), "zh-cn");
assert_eq!(f("", "zh_TW", false), "zh-tw");
assert_eq!(f("", "ja-JP", false), "ja");
}
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "تبديل الشاشة"), ("Switch display", "تبديل الشاشة"),
("Show monitor switch button on the main toolbar", "إظهار زر تبديل الشاشة على شريط الأدوات الرئيسي"), ("Show monitor switch button on the main toolbar", "إظهار زر تبديل الشاشة على شريط الأدوات الرئيسي"),
("Show on the minimized toolbar", "الإظهار على شريط الأدوات المُصغّر"), ("Show on the minimized toolbar", "الإظهار على شريط الأدوات المُصغّر"),
("All monitors", "جميع الشاشات"),
("#{} monitor", "الشاشة رقم {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Пераключыць дысплэй"), ("Switch display", "Пераключыць дысплэй"),
("Show monitor switch button on the main toolbar", "Паказваць кнопку пераключэння манітора на галоўнай панэлі інструментаў"), ("Show monitor switch button on the main toolbar", "Паказваць кнопку пераключэння манітора на галоўнай панэлі інструментаў"),
("Show on the minimized toolbar", "Паказваць на згорнутай панэлі інструментаў"), ("Show on the minimized toolbar", "Паказваць на згорнутай панэлі інструментаў"),
("All monitors", "Усе манітори"),
("#{} monitor", "Манітор {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Превключване на дисплея"), ("Switch display", "Превключване на дисплея"),
("Show monitor switch button on the main toolbar", "Показване на бутона за превключване на монитора в главната лента с инструменти"), ("Show monitor switch button on the main toolbar", "Показване на бутона за превключване на монитора в главната лента с инструменти"),
("Show on the minimized toolbar", "Показване в минимизираната лента с инструменти"), ("Show on the minimized toolbar", "Показване в минимизираната лента с инструменти"),
("All monitors", "Всички монитори"),
("#{} monitor", "Монитор {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Canvia de pantalla"), ("Switch display", "Canvia de pantalla"),
("Show monitor switch button on the main toolbar", "Mostra el botó de canvi de monitor a la barra deines principal"), ("Show monitor switch button on the main toolbar", "Mostra el botó de canvi de monitor a la barra deines principal"),
("Show on the minimized toolbar", "Mostra a la barra deines minimitzada"), ("Show on the minimized toolbar", "Mostra a la barra deines minimitzada"),
("All monitors", "Tots els monitors"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "切换显示器"), ("Switch display", "切换显示器"),
("Show monitor switch button on the main toolbar", "在主工具栏上显示显示器切换按钮"), ("Show monitor switch button on the main toolbar", "在主工具栏上显示显示器切换按钮"),
("Show on the minimized toolbar", "在最小化工具栏上显示"), ("Show on the minimized toolbar", "在最小化工具栏上显示"),
("All monitors", "所有显示器"),
("#{} monitor", "{}号显示器"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Přepnout obrazovku"), ("Switch display", "Přepnout obrazovku"),
("Show monitor switch button on the main toolbar", "Zobrazit tlačítko přepnutí monitoru na hlavním panelu nástrojů"), ("Show monitor switch button on the main toolbar", "Zobrazit tlačítko přepnutí monitoru na hlavním panelu nástrojů"),
("Show on the minimized toolbar", "Zobrazit na minimalizovaném panelu nástrojů"), ("Show on the minimized toolbar", "Zobrazit na minimalizovaném panelu nástrojů"),
("All monitors", "Všechny monitory"),
("#{} monitor", "Monitor č. {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Skift skærm"), ("Switch display", "Skift skærm"),
("Show monitor switch button on the main toolbar", "Vis knap til skærmskift på hovedværktøjslinjen"), ("Show monitor switch button on the main toolbar", "Vis knap til skærmskift på hovedværktøjslinjen"),
("Show on the minimized toolbar", "Vis på den minimerede værktøjslinje"), ("Show on the minimized toolbar", "Vis på den minimerede værktøjslinje"),
("All monitors", "Alle skærme"),
("#{} monitor", "Skærm {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Anzeige wechseln"), ("Switch display", "Anzeige wechseln"),
("Show monitor switch button on the main toolbar", "Schaltfläche zum Monitorwechsel in der Haupt-Symbolleiste anzeigen"), ("Show monitor switch button on the main toolbar", "Schaltfläche zum Monitorwechsel in der Haupt-Symbolleiste anzeigen"),
("Show on the minimized toolbar", "In der minimierten Symbolleiste anzeigen"), ("Show on the minimized toolbar", "In der minimierten Symbolleiste anzeigen"),
("All monitors", "Alle Bildschirme"),
("#{} monitor", "Bildschirm {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Εναλλαγή οθόνης"), ("Switch display", "Εναλλαγή οθόνης"),
("Show monitor switch button on the main toolbar", "Εμφάνιση κουμπιού εναλλαγής οθόνης στην κύρια γραμμή εργαλείων"), ("Show monitor switch button on the main toolbar", "Εμφάνιση κουμπιού εναλλαγής οθόνης στην κύρια γραμμή εργαλείων"),
("Show on the minimized toolbar", "Εμφάνιση στην ελαχιστοποιημένη γραμμή εργαλείων"), ("Show on the minimized toolbar", "Εμφάνιση στην ελαχιστοποιημένη γραμμή εργαλείων"),
("All monitors", "Όλες οι οθόνες"),
("#{} monitor", "Οθόνη {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Ŝalti ekranon"), ("Switch display", "Ŝalti ekranon"),
("Show monitor switch button on the main toolbar", "Montri ekran-ŝaltan butonon en la ĉefa ilobreto"), ("Show monitor switch button on the main toolbar", "Montri ekran-ŝaltan butonon en la ĉefa ilobreto"),
("Show on the minimized toolbar", "Montri en la minimumigita ilobreto"), ("Show on the minimized toolbar", "Montri en la minimumigita ilobreto"),
("All monitors", "Ĉiuj monitoroj"),
("#{} monitor", "Monitoro {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Cambiar de pantalla"), ("Switch display", "Cambiar de pantalla"),
("Show monitor switch button on the main toolbar", "Mostrar el botón de cambio de monitor en la barra de herramientas principal"), ("Show monitor switch button on the main toolbar", "Mostrar el botón de cambio de monitor en la barra de herramientas principal"),
("Show on the minimized toolbar", "Mostrar en la barra de herramientas minimizada"), ("Show on the minimized toolbar", "Mostrar en la barra de herramientas minimizada"),
("All monitors", "Todos los monitores"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Vaheta kuva"), ("Switch display", "Vaheta kuva"),
("Show monitor switch button on the main toolbar", "Näita monitori vahetamise nuppu peamisel tööriistaribal"), ("Show monitor switch button on the main toolbar", "Näita monitori vahetamise nuppu peamisel tööriistaribal"),
("Show on the minimized toolbar", "Näita minimeeritud tööriistaribal"), ("Show on the minimized toolbar", "Näita minimeeritud tööriistaribal"),
("All monitors", "Kõik kuvarid"),
("#{} monitor", "Kuvar {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Aldatu pantaila"), ("Switch display", "Aldatu pantaila"),
("Show monitor switch button on the main toolbar", "Erakutsi monitorea aldatzeko botoia tresna-barra nagusian"), ("Show monitor switch button on the main toolbar", "Erakutsi monitorea aldatzeko botoia tresna-barra nagusian"),
("Show on the minimized toolbar", "Erakutsi minimizatutako tresna-barran"), ("Show on the minimized toolbar", "Erakutsi minimizatutako tresna-barran"),
("All monitors", "Monitore guztiak"),
("#{} monitor", "{}. monitorea"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "تعویض نمایشگر"), ("Switch display", "تعویض نمایشگر"),
("Show monitor switch button on the main toolbar", "نمایش دکمه تعویض نمایشگر در نوار ابزار اصلی"), ("Show monitor switch button on the main toolbar", "نمایش دکمه تعویض نمایشگر در نوار ابزار اصلی"),
("Show on the minimized toolbar", "نمایش در نوار ابزار کوچک‌شده"), ("Show on the minimized toolbar", "نمایش در نوار ابزار کوچک‌شده"),
("All monitors", "همه نمایشگرها"),
("#{} monitor", "نمایشگر {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Vaihda näyttöä"), ("Switch display", "Vaihda näyttöä"),
("Show monitor switch button on the main toolbar", "Näytä näytön vaihtopainike päätyökalurivillä"), ("Show monitor switch button on the main toolbar", "Näytä näytön vaihtopainike päätyökalurivillä"),
("Show on the minimized toolbar", "Näytä pienennetyssä työkalurivissä"), ("Show on the minimized toolbar", "Näytä pienennetyssä työkalurivissä"),
("All monitors", "Kaikki näytöt"),
("#{} monitor", "Näyttö {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Changer d’écran"), ("Switch display", "Changer d’écran"),
("Show monitor switch button on the main toolbar", "Afficher le bouton de changement d’écran dans la barre doutils principale"), ("Show monitor switch button on the main toolbar", "Afficher le bouton de changement d’écran dans la barre doutils principale"),
("Show on the minimized toolbar", "Afficher dans la barre doutils réduite"), ("Show on the minimized toolbar", "Afficher dans la barre doutils réduite"),
("All monitors", "Tous les moniteurs"),
("#{} monitor", "Moniteur {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "ეკრანის გადართვა"), ("Switch display", "ეკრანის გადართვა"),
("Show monitor switch button on the main toolbar", "მონიტორის გადართვის ღილაკის ჩვენება მთავარ ხელსაწყოთა ზოლზე"), ("Show monitor switch button on the main toolbar", "მონიტორის გადართვის ღილაკის ჩვენება მთავარ ხელსაწყოთა ზოლზე"),
("Show on the minimized toolbar", "ჩვენება ჩაკეცილ ხელსაწყოთა ზოლზე"), ("Show on the minimized toolbar", "ჩვენება ჩაკეცილ ხელსაწყოთა ზოლზე"),
("All monitors", "ყველა მონიტორი"),
("#{} monitor", "მონიტორი {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "ડિસ્પ્લે બદલો"), ("Switch display", "ડિસ્પ્લે બદલો"),
("Show monitor switch button on the main toolbar", "મુખ્ય ટૂલબાર પર મોનિટર સ્વિચ બટન બતાવો"), ("Show monitor switch button on the main toolbar", "મુખ્ય ટૂલબાર પર મોનિટર સ્વિચ બટન બતાવો"),
("Show on the minimized toolbar", "ન્યૂનતમ કરેલા ટૂલબાર પર બતાવો"), ("Show on the minimized toolbar", "ન્યૂનતમ કરેલા ટૂલબાર પર બતાવો"),
("All monitors", "બધા મોનિટર"),
("#{} monitor", "મોનિટર {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "החלפת צג"), ("Switch display", "החלפת צג"),
("Show monitor switch button on the main toolbar", "הצגת לחצן החלפת צג בסרגל הכלים הראשי"), ("Show monitor switch button on the main toolbar", "הצגת לחצן החלפת צג בסרגל הכלים הראשי"),
("Show on the minimized toolbar", "הצגה בסרגל הכלים הממוזער"), ("Show on the minimized toolbar", "הצגה בסרגל הכלים הממוזער"),
("All monitors", "כל המסכים"),
("#{} monitor", "מסך {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "डिस्प्ले बदलें"), ("Switch display", "डिस्प्ले बदलें"),
("Show monitor switch button on the main toolbar", "मुख्य टूलबार पर मॉनिटर स्विच बटन दिखाएं"), ("Show monitor switch button on the main toolbar", "मुख्य टूलबार पर मॉनिटर स्विच बटन दिखाएं"),
("Show on the minimized toolbar", "न्यूनतम किए गए टूलबार पर दिखाएं"), ("Show on the minimized toolbar", "न्यूनतम किए गए टूलबार पर दिखाएं"),
("All monitors", "सभी मॉनिटर"),
("#{} monitor", "मॉनिटर {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Promijeni zaslon"), ("Switch display", "Promijeni zaslon"),
("Show monitor switch button on the main toolbar", "Prikaži gumb za prebacivanje monitora na glavnoj alatnoj traci"), ("Show monitor switch button on the main toolbar", "Prikaži gumb za prebacivanje monitora na glavnoj alatnoj traci"),
("Show on the minimized toolbar", "Prikaži na minimiziranoj alatnoj traci"), ("Show on the minimized toolbar", "Prikaži na minimiziranoj alatnoj traci"),
("All monitors", "Svi monitori"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Kijelző váltása"), ("Switch display", "Kijelző váltása"),
("Show monitor switch button on the main toolbar", "Monitorváltó gomb megjelenítése a fő eszköztáron"), ("Show monitor switch button on the main toolbar", "Monitorváltó gomb megjelenítése a fő eszköztáron"),
("Show on the minimized toolbar", "Megjelenítés a kis méretű eszköztáron"), ("Show on the minimized toolbar", "Megjelenítés a kis méretű eszköztáron"),
("All monitors", "Minden monitor"),
("#{} monitor", "{}. monitor"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Ganti tampilan"), ("Switch display", "Ganti tampilan"),
("Show monitor switch button on the main toolbar", "Tampilkan tombol pengalih monitor di bilah alat utama"), ("Show monitor switch button on the main toolbar", "Tampilkan tombol pengalih monitor di bilah alat utama"),
("Show on the minimized toolbar", "Tampilkan di bilah alat yang diperkecil"), ("Show on the minimized toolbar", "Tampilkan di bilah alat yang diperkecil"),
("All monitors", "Semua monitor"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Cambia schermo"), ("Switch display", "Cambia schermo"),
("Show monitor switch button on the main toolbar", "Visualizza nella barra strumenti principale il pulsante per il cambio schermo"), ("Show monitor switch button on the main toolbar", "Visualizza nella barra strumenti principale il pulsante per il cambio schermo"),
("Show on the minimized toolbar", "Visualizza nella barra strumenti ridotta a icona"), ("Show on the minimized toolbar", "Visualizza nella barra strumenti ridotta a icona"),
("All monitors", "Tutti gli schermi"),
("#{} monitor", "Schermo {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "ディスプレイを切り替え"), ("Switch display", "ディスプレイを切り替え"),
("Show monitor switch button on the main toolbar", "メインツールバーにモニター切り替えボタンを表示"), ("Show monitor switch button on the main toolbar", "メインツールバーにモニター切り替えボタンを表示"),
("Show on the minimized toolbar", "最小化したツールバーに表示"), ("Show on the minimized toolbar", "最小化したツールバーに表示"),
("All monitors", "すべてのディスプレイ"),
("#{} monitor", "ディスプレイ {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "디스플레이 전환"), ("Switch display", "디스플레이 전환"),
("Show monitor switch button on the main toolbar", "기본 도구 모음에 모니터 전환 버튼 표시"), ("Show monitor switch button on the main toolbar", "기본 도구 모음에 모니터 전환 버튼 표시"),
("Show on the minimized toolbar", "최소화된 도구 모음에 표시"), ("Show on the minimized toolbar", "최소화된 도구 모음에 표시"),
("All monitors", "모든 모니터"),
("#{} monitor", "{}번 모니터"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Дисплейді ауыстыру"), ("Switch display", "Дисплейді ауыстыру"),
("Show monitor switch button on the main toolbar", "Негізгі құралдар тақтасында мониторды ауыстыру түймесін көрсету"), ("Show monitor switch button on the main toolbar", "Негізгі құралдар тақтасында мониторды ауыстыру түймесін көрсету"),
("Show on the minimized toolbar", "Кішірейтілген құралдар тақтасында көрсету"), ("Show on the minimized toolbar", "Кішірейтілген құралдар тақтасында көрсету"),
("All monitors", "Барлық мониторлар"),
("#{} monitor", "Монитор {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Perjungti ekraną"), ("Switch display", "Perjungti ekraną"),
("Show monitor switch button on the main toolbar", "Rodyti monitoriaus perjungimo mygtuką pagrindinėje įrankių juostoje"), ("Show monitor switch button on the main toolbar", "Rodyti monitoriaus perjungimo mygtuką pagrindinėje įrankių juostoje"),
("Show on the minimized toolbar", "Rodyti sumažintoje įrankių juostoje"), ("Show on the minimized toolbar", "Rodyti sumažintoje įrankių juostoje"),
("All monitors", "Visi monitoriai"),
("#{} monitor", "Monitorius {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Pārslēgt displeju"), ("Switch display", "Pārslēgt displeju"),
("Show monitor switch button on the main toolbar", "Rādīt monitora pārslēgšanas pogu galvenajā rīkjoslā"), ("Show monitor switch button on the main toolbar", "Rādīt monitora pārslēgšanas pogu galvenajā rīkjoslā"),
("Show on the minimized toolbar", "Rādīt minimizētajā rīkjoslā"), ("Show on the minimized toolbar", "Rādīt minimizētajā rīkjoslā"),
("All monitors", "Visi monitori"),
("#{} monitor", "Monitors {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "ഡിസ്പ്ലേ മാറ്റുക"), ("Switch display", "ഡിസ്പ്ലേ മാറ്റുക"),
("Show monitor switch button on the main toolbar", "പ്രധാന ടൂൾബാറിൽ മോണിറ്റർ സ്വിച്ച് ബട്ടൺ കാണിക്കുക"), ("Show monitor switch button on the main toolbar", "പ്രധാന ടൂൾബാറിൽ മോണിറ്റർ സ്വിച്ച് ബട്ടൺ കാണിക്കുക"),
("Show on the minimized toolbar", "ചെറുതാക്കിയ ടൂൾബാറിൽ കാണിക്കുക"), ("Show on the minimized toolbar", "ചെറുതാക്കിയ ടൂൾബാറിൽ കാണിക്കുക"),
("All monitors", "എല്ലാ മോണിറ്ററുകളും"),
("#{} monitor", "മോണിറ്റർ {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Bytt skjerm"), ("Switch display", "Bytt skjerm"),
("Show monitor switch button on the main toolbar", "Vis knapp for skjermbytte på hovedverktøylinjen"), ("Show monitor switch button on the main toolbar", "Vis knapp for skjermbytte på hovedverktøylinjen"),
("Show on the minimized toolbar", "Vis på den minimerte verktøylinjen"), ("Show on the minimized toolbar", "Vis på den minimerte verktøylinjen"),
("All monitors", "Alle skjermer"),
("#{} monitor", "Skjerm {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Beeldscherm wisselen"), ("Switch display", "Beeldscherm wisselen"),
("Show monitor switch button on the main toolbar", "Knop voor monitorwisseling weergeven op de hoofdwerkbalk"), ("Show monitor switch button on the main toolbar", "Knop voor monitorwisseling weergeven op de hoofdwerkbalk"),
("Show on the minimized toolbar", "Weergeven op de geminimaliseerde werkbalk"), ("Show on the minimized toolbar", "Weergeven op de geminimaliseerde werkbalk"),
("All monitors", "Alle monitoren"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Przełącz ekran"), ("Switch display", "Przełącz ekran"),
("Show monitor switch button on the main toolbar", "Pokaż przycisk przełączania monitora na głównym pasku narzędzi"), ("Show monitor switch button on the main toolbar", "Pokaż przycisk przełączania monitora na głównym pasku narzędzi"),
("Show on the minimized toolbar", "Pokaż na zminimalizowanym pasku narzędzi"), ("Show on the minimized toolbar", "Pokaż na zminimalizowanym pasku narzędzi"),
("All monitors", "Wszystkie ekrany"),
("#{} monitor", "Ekran {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Trocar de ecrã"), ("Switch display", "Trocar de ecrã"),
("Show monitor switch button on the main toolbar", "Mostrar o botão de troca de monitor na barra de ferramentas principal"), ("Show monitor switch button on the main toolbar", "Mostrar o botão de troca de monitor na barra de ferramentas principal"),
("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"), ("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"),
("All monitors", "Todos os monitores"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Trocar de tela"), ("Switch display", "Trocar de tela"),
("Show monitor switch button on the main toolbar", "Mostrar botão de troca de tela na barra de ferramentas"), ("Show monitor switch button on the main toolbar", "Mostrar botão de troca de tela na barra de ferramentas"),
("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"), ("Show on the minimized toolbar", "Mostrar na barra de ferramentas minimizada"),
("All monitors", "Todas as telas"),
("#{} monitor", "Tela {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Comută afișajul"), ("Switch display", "Comută afișajul"),
("Show monitor switch button on the main toolbar", "Afișează butonul de comutare a monitorului în bara de instrumente principală"), ("Show monitor switch button on the main toolbar", "Afișează butonul de comutare a monitorului în bara de instrumente principală"),
("Show on the minimized toolbar", "Afișează în bara de instrumente minimizată"), ("Show on the minimized toolbar", "Afișează în bara de instrumente minimizată"),
("All monitors", "Toate monitoarele"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Переключить дисплей"), ("Switch display", "Переключить дисплей"),
("Show monitor switch button on the main toolbar", "Показывать кнопку переключения монитора на главной панели инструментов"), ("Show monitor switch button on the main toolbar", "Показывать кнопку переключения монитора на главной панели инструментов"),
("Show on the minimized toolbar", "Показывать на свёрнутой панели инструментов"), ("Show on the minimized toolbar", "Показывать на свёрнутой панели инструментов"),
("All monitors", "Все мониторы"),
("#{} monitor", "Монитор {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Càmbia ischermu"), ("Switch display", "Càmbia ischermu"),
("Show monitor switch button on the main toolbar", "Mustra su butone de càmbiu de monitor in sa barra de aina printzipale"), ("Show monitor switch button on the main toolbar", "Mustra su butone de càmbiu de monitor in sa barra de aina printzipale"),
("Show on the minimized toolbar", "Mustra in sa barra de aina minimizada"), ("Show on the minimized toolbar", "Mustra in sa barra de aina minimizada"),
("All monitors", "Totu sos ischermos"),
("#{} monitor", "Ischermu {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Prepnúť obrazovku"), ("Switch display", "Prepnúť obrazovku"),
("Show monitor switch button on the main toolbar", "Zobraziť tlačidlo prepnutia monitora na hlavnom paneli nástrojov"), ("Show monitor switch button on the main toolbar", "Zobraziť tlačidlo prepnutia monitora na hlavnom paneli nástrojov"),
("Show on the minimized toolbar", "Zobraziť na minimalizovanom paneli nástrojov"), ("Show on the minimized toolbar", "Zobraziť na minimalizovanom paneli nástrojov"),
("All monitors", "Všetky monitory"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Preklopi zaslon"), ("Switch display", "Preklopi zaslon"),
("Show monitor switch button on the main toolbar", "Pokaži gumb za preklop monitorja v glavni orodni vrstici"), ("Show monitor switch button on the main toolbar", "Pokaži gumb za preklop monitorja v glavni orodni vrstici"),
("Show on the minimized toolbar", "Pokaži v pomanjšani orodni vrstici"), ("Show on the minimized toolbar", "Pokaži v pomanjšani orodni vrstici"),
("All monitors", "Vsi zasloni"),
("#{} monitor", "Zaslon {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Ndërro ekranin"), ("Switch display", "Ndërro ekranin"),
("Show monitor switch button on the main toolbar", "Shfaq butonin e ndërrimit të monitorit te shiriti kryesor i veglave"), ("Show monitor switch button on the main toolbar", "Shfaq butonin e ndërrimit të monitorit te shiriti kryesor i veglave"),
("Show on the minimized toolbar", "Shfaq te shiriti i minimizuar i veglave"), ("Show on the minimized toolbar", "Shfaq te shiriti i minimizuar i veglave"),
("All monitors", "Të gjithë monitorët"),
("#{} monitor", "Monitori {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Промени екран"), ("Switch display", "Промени екран"),
("Show monitor switch button on the main toolbar", "Прикажи дугме за пребацивање монитора на главној траци са алаткама"), ("Show monitor switch button on the main toolbar", "Прикажи дугме за пребацивање монитора на главној траци са алаткама"),
("Show on the minimized toolbar", "Прикажи на умањеној траци са алаткама"), ("Show on the minimized toolbar", "Прикажи на умањеној траци са алаткама"),
("All monitors", "Svi monitori"),
("#{} monitor", "Monitor {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Växla skärm"), ("Switch display", "Växla skärm"),
("Show monitor switch button on the main toolbar", "Visa knapp för skärmväxling i huvudverktygsfältet"), ("Show monitor switch button on the main toolbar", "Visa knapp för skärmväxling i huvudverktygsfältet"),
("Show on the minimized toolbar", "Visa i det minimerade verktygsfältet"), ("Show on the minimized toolbar", "Visa i det minimerade verktygsfältet"),
("All monitors", "Alla skärmar"),
("#{} monitor", "Skärm {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "திரையை மாற்று"), ("Switch display", "திரையை மாற்று"),
("Show monitor switch button on the main toolbar", "முதன்மை கருவிப்பட்டையில் திரை மாற்று பொத்தானைக் காட்டு"), ("Show monitor switch button on the main toolbar", "முதன்மை கருவிப்பட்டையில் திரை மாற்று பொத்தானைக் காட்டு"),
("Show on the minimized toolbar", "சிறிதாக்கப்பட்ட கருவிப்பட்டையில் காட்டு"), ("Show on the minimized toolbar", "சிறிதாக்கப்பட்ட கருவிப்பட்டையில் காட்டு"),
("All monitors", "அனைத்து மானிட்டர்களும்"),
("#{} monitor", "மானிட்டர் {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", ""), ("Switch display", ""),
("Show monitor switch button on the main toolbar", ""), ("Show monitor switch button on the main toolbar", ""),
("Show on the minimized toolbar", ""), ("Show on the minimized toolbar", ""),
("All monitors", ""),
("#{} monitor", ""),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "สลับจอแสดงผล"), ("Switch display", "สลับจอแสดงผล"),
("Show monitor switch button on the main toolbar", "แสดงปุ่มสลับจอภาพบนแถบเครื่องมือหลัก"), ("Show monitor switch button on the main toolbar", "แสดงปุ่มสลับจอภาพบนแถบเครื่องมือหลัก"),
("Show on the minimized toolbar", "แสดงบนแถบเครื่องมือที่ย่อเล็กสุด"), ("Show on the minimized toolbar", "แสดงบนแถบเครื่องมือที่ย่อเล็กสุด"),
("All monitors", "จอภาพทั้งหมด"),
("#{} monitor", "จอภาพ {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Ekranı değiştir"), ("Switch display", "Ekranı değiştir"),
("Show monitor switch button on the main toolbar", "Ana araç çubuğunda monitör değiştirme düğmesini göster"), ("Show monitor switch button on the main toolbar", "Ana araç çubuğunda monitör değiştirme düğmesini göster"),
("Show on the minimized toolbar", "Simge durumuna küçültülmüş araç çubuğunda göster"), ("Show on the minimized toolbar", "Simge durumuna küçültülmüş araç çubuğunda göster"),
("All monitors", "Tüm monitörler"),
("#{} monitor", "Monitör {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "切換螢幕"), ("Switch display", "切換螢幕"),
("Show monitor switch button on the main toolbar", "在主工具列上顯示螢幕切換按鈕"), ("Show monitor switch button on the main toolbar", "在主工具列上顯示螢幕切換按鈕"),
("Show on the minimized toolbar", "在最小化工具列上顯示"), ("Show on the minimized toolbar", "在最小化工具列上顯示"),
("All monitors", "所有顯示器"),
("#{} monitor", "{}號顯示器"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Перемкнути дисплей"), ("Switch display", "Перемкнути дисплей"),
("Show monitor switch button on the main toolbar", "Показувати кнопку перемикання монітора на головній панелі інструментів"), ("Show monitor switch button on the main toolbar", "Показувати кнопку перемикання монітора на головній панелі інструментів"),
("Show on the minimized toolbar", "Показувати на згорнутій панелі інструментів"), ("Show on the minimized toolbar", "Показувати на згорнутій панелі інструментів"),
("All monitors", "Усі монітори"),
("#{} monitor", "Монітор {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+2
View File
@@ -761,5 +761,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Switch display", "Chuyển màn hình"), ("Switch display", "Chuyển màn hình"),
("Show monitor switch button on the main toolbar", "Hiển thị nút chuyển đổi màn hình trên thanh công cụ chính"), ("Show monitor switch button on the main toolbar", "Hiển thị nút chuyển đổi màn hình trên thanh công cụ chính"),
("Show on the minimized toolbar", "Hiển thị trên thanh công cụ thu nhỏ"), ("Show on the minimized toolbar", "Hiển thị trên thanh công cụ thu nhỏ"),
("All monitors", "Tất cả màn hình"),
("#{} monitor", "Màn hình {}"),
].iter().cloned().collect(); ].iter().cloned().collect();
} }
+8
View File
@@ -3944,6 +3944,14 @@ pub fn is_x64() -> bool {
unsafe { sys_info.u.s().wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 } unsafe { sys_info.u.s().wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 }
} }
pub fn release_arch_suffix() -> Option<&'static str> {
match std::env::consts::ARCH {
"x86_64" => Some("x86_64"),
"aarch64" => Some("aarch64"),
_ => None,
}
}
pub fn try_kill_rustdesk_main_window_process() -> ResultType<()> { pub fn try_kill_rustdesk_main_window_process() -> ResultType<()> {
// Kill rustdesk.exe without extra arg, should only be called by --server // Kill rustdesk.exe without extra arg, should only be called by --server
// We can find the exact process which occupies the ipc, see more from https://github.com/winsiderss/systeminformer // We can find the exact process which occupies the ipc, see more from https://github.com/winsiderss/systeminformer
+1 -1
View File
@@ -1,7 +1,7 @@
/// Url handler based on dbus /// Url handler based on dbus
/// ///
/// Note: /// Note:
/// On linux, we use dbus to communicate multiple rustdesk process. /// On linux, we use dbus to communicate between multiple rustdesk processes.
/// [Flutter]: handle uni links for linux /// [Flutter]: handle uni links for linux
use dbus::blocking::Connection; use dbus::blocking::Connection;
use dbus_crossroads::{Crossroads, IfaceBuilder}; use dbus_crossroads::{Crossroads, IfaceBuilder};
+71 -18
View File
@@ -72,6 +72,48 @@ function getExt(name) {
class JobTable: Reactor.Component { class JobTable: Reactor.Component {
this var jobs = []; this var jobs = [];
this var job_map = {}; this var job_map = {};
this var next_conflict_batch_id = 1;
this var remembered_write_strategy = {};
function nextConflictBatchId() {
return this.next_conflict_batch_id++;
}
function getRememberedWriteStrategy(conflict_batch_id) {
var is_override = this.remembered_write_strategy[conflict_batch_id];
if (is_override == true || is_override == false) return is_override;
return null;
}
function rememberWriteStrategy(conflict_batch_id, is_override) {
this.remembered_write_strategy[conflict_batch_id] = is_override;
}
function cancelTransferJob(job) {
job.finished = true;
job.err = "cancel";
this.updateJob(job);
}
function cancelTransferConflictBatch(id) {
var job = this.job_map[id];
if (!job) return;
var conflict_batch_id = job.conflict_batch_id;
if (conflict_batch_id == null) {
this.cancelTransferJob(job);
handler.cancel_job(job.id);
refreshDir(!job.is_remote);
return;
}
delete this.remembered_write_strategy[conflict_batch_id];
for (var i = 0; i < this.jobs.length; ++i) {
var current_job = this.jobs[i];
if (current_job.conflict_batch_id != conflict_batch_id || current_job.finished) continue;
this.cancelTransferJob(current_job);
handler.cancel_job(current_job.id);
}
refreshDir(!job.is_remote);
}
function render() { function render() {
var me = this; var me = this;
@@ -109,10 +151,12 @@ class JobTable: Reactor.Component {
function clearAllJobs() { function clearAllJobs() {
this.jobs = []; this.jobs = [];
this.job_map = {}; this.job_map = {};
this.next_conflict_batch_id = 1;
this.remembered_write_strategy = {};
this.update(); this.update();
} }
function send(path, is_remote) { function send(path, is_remote, conflict_batch_id = null) {
var to; var to;
var show_hidden; var show_hidden;
if (is_remote) { if (is_remote) {
@@ -123,13 +167,15 @@ class JobTable: Reactor.Component {
show_hidden = file_transfer.local_folder_view.show_hidden; show_hidden = file_transfer.local_folder_view.show_hidden;
} }
if (!to) return; if (!to) return;
if (conflict_batch_id == null) conflict_batch_id = this.nextConflictBatchId();
to += handler.get_path_sep(!is_remote) + getFileName(is_remote, path); to += handler.get_path_sep(!is_remote) + getFileName(is_remote, path);
var id = handler.get_next_job_id(); var id = handler.get_next_job_id();
this.jobs.push({ type: "transfer", this.jobs.push({ type: "transfer",
id: id, path: path, to: to, id: id, path: path, to: to,
include_hidden: show_hidden, include_hidden: show_hidden,
is_remote: is_remote, is_remote: is_remote,
is_last: false is_last: false,
conflict_batch_id: conflict_batch_id
}); });
this.job_map[id] = this.jobs[this.jobs.length - 1]; this.job_map[id] = this.jobs[this.jobs.length - 1];
handler.send_files(id, 0, path, to, 0, show_hidden, is_remote); handler.send_files(id, 0, path, to, 0, show_hidden, is_remote);
@@ -141,7 +187,8 @@ class JobTable: Reactor.Component {
var job = { type: "transfer", var job = { type: "transfer",
id: id, path: path, to: to, id: id, path: path, to: to,
include_hidden: show_hidden, include_hidden: show_hidden,
is_remote: is_remote, is_last: true, file_num: file_num }; is_remote: is_remote, is_last: true, file_num: file_num,
conflict_batch_id: this.nextConflictBatchId() };
this.jobs.push(job); this.jobs.push(job);
this.job_map[id] = this.jobs[this.jobs.length - 1]; this.job_map[id] = this.jobs[this.jobs.length - 1];
handler.update_next_job_id(id + 1); handler.update_next_job_id(id + 1);
@@ -230,6 +277,7 @@ class JobTable: Reactor.Component {
else return translate("Waiting"); else return translate("Waiting");
} }
} }
if (job.err == "cancel") return translate("Cancel");
if (!job.entries) return translate("Waiting"); if (!job.entries) return translate("Waiting");
var i = job.file_num + 1; var i = job.file_num + 1;
var n = job.num_entries || job.entries.length; var n = job.num_entries || job.entries.length;
@@ -262,6 +310,8 @@ class JobTable: Reactor.Component {
function updateJobStatus(id, file_num = -1, err = null, speed = null, finished_size = 0) { function updateJobStatus(id, file_num = -1, err = null, speed = null, finished_size = 0) {
var job = this.job_map[id]; var job = this.job_map[id];
if (!job) return;
if (job.finished && job.err == "cancel") return;
if (job.type == "del-file"){ if (job.type == "del-file"){
job.finished = true; job.finished = true;
job.err = err; job.err = err;
@@ -269,7 +319,6 @@ class JobTable: Reactor.Component {
this.updateJob(job); this.updateJob(job);
return; return;
} }
if (!job) return;
if (file_num < job.file_num) return; if (file_num < job.file_num) return;
job.file_num = file_num; job.file_num = file_num;
var n = job.num_entries || job.entries.length; var n = job.num_entries || job.entries.length;
@@ -601,8 +650,9 @@ class FolderView : Reactor.Component {
event click $(.send) () { event click $(.send) () {
var rows = this.getCurrentRows(); var rows = this.getCurrentRows();
if (!rows || rows.length == 0) return; if (!rows || rows.length == 0) return;
var conflict_batch_id = file_transfer.job_table.nextConflictBatchId();
for (var i = 0; i < rows.length; ++i) { for (var i = 0; i < rows.length; ++i) {
file_transfer.job_table.send(rows[i][0], this.is_remote); file_transfer.job_table.send(rows[i][0], this.is_remote, conflict_batch_id);
} }
} }
@@ -780,6 +830,13 @@ handler.confirmDeleteFiles = function(id, i, name) {
handler.overrideFileConfirm = function(id, file_num, to, is_upload, is_identical) { handler.overrideFileConfirm = function(id, file_num, to, is_upload, is_identical) {
var jt = file_transfer.job_table; var jt = file_transfer.job_table;
var job = jt.job_map[id];
if (!job || job.finished) return;
var remembered = jt.getRememberedWriteStrategy(job.conflict_batch_id);
if (remembered == true || remembered == false) {
handler.set_write_override(id, file_num, remembered, true, is_upload);
return;
}
var identical_msg = is_identical ? translate("identical_file_tip"): ""; var identical_msg = is_identical ? translate("identical_file_tip"): "";
msgbox("custom-skip", "Confirm Write Strategy", "<div .form> \ msgbox("custom-skip", "Confirm Write Strategy", "<div .form> \
<div>" + translate('Overwrite') + " " + translate('files') + ".</div> \ <div>" + translate('Overwrite') + " " + translate('files') + ".</div> \
@@ -788,22 +845,18 @@ handler.overrideFileConfirm = function(id, file_num, to, is_upload, is_identical
<div>" + identical_msg + "</div> \ <div>" + identical_msg + "</div> \
<div><button|checkbox(remember) {ts}>" + translate('Do this for all conflicts') + "</button></div> \ <div><button|checkbox(remember) {ts}>" + translate('Do this for all conflicts') + "</button></div> \
</div>", "", function(res=null) { </div>", "", function(res=null) {
var current_job = jt.job_map[id];
if (!current_job || current_job.finished) return;
if (!res) { if (!res) {
jt.updateJobStatus(id, -1, "cancel"); jt.cancelTransferConflictBatch(id);
handler.cancel_job(id); return;
} else if (res.skip) {
if (res.remember){
handler.set_write_override(id,file_num,false,true, is_upload); //
} else {
handler.set_write_override(id,file_num,false,false,is_upload); //
}
} else {
if (res.remember){
handler.set_write_override(id,file_num,true,true,is_upload); //
} else {
handler.set_write_override(id,file_num,true,false,is_upload); //
} }
var is_override = !res.skip;
var remember = res.remember ? true : false;
if (remember) {
jt.rememberWriteStrategy(current_job.conflict_batch_id, is_override);
} }
handler.set_write_override(id, file_num, is_override, remember, is_upload);
}); });
} }
+2
View File
@@ -902,8 +902,10 @@ pub fn get_async_job_status() -> String {
#[inline] #[inline]
pub fn get_langs() -> String { pub fn get_langs() -> String {
use serde_json::json; use serde_json::json;
let hide_cjk = crate::lang::cjk_ui_unavailable();
let mut x: Vec<(&str, String)> = crate::lang::LANGS let mut x: Vec<(&str, String)> = crate::lang::LANGS
.iter() .iter()
.filter(|a| !hide_cjk || !crate::lang::is_cjk_lang(a.0))
.map(|a| (a.0, format!("{} ({})", a.1, a.0))) .map(|a| (a.0, format!("{} ({})", a.1, a.0)))
.collect(); .collect();
x.sort_by(|a, b| a.0.cmp(b.0)); x.sort_by(|a, b| a.0.cmp(b.0));
+8 -1
View File
@@ -136,10 +136,17 @@ fn check_update(manually: bool) -> ResultType<()> {
let version = download_url.split('/').last().unwrap_or_default(); let version = download_url.split('/').last().unwrap_or_default();
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let download_url = if cfg!(feature = "flutter") { let download_url = if cfg!(feature = "flutter") {
let Some(arch) = crate::platform::windows::release_arch_suffix() else {
bail!(
"Unsupported Windows release architecture: {}",
std::env::consts::ARCH
);
};
format!( format!(
"{}/rustdesk-{}-x86_64.{}", "{}/rustdesk-{}-{}.{}",
download_url, download_url,
version, version,
arch,
if update_msi { "msi" } else { "exe" } if update_msi { "msi" } else { "exe" }
) )
} else { } else {