From 66876eaab0beb506f6bf618d6a88af87eeb37f62 Mon Sep 17 00:00:00 2001 From: Kaede Akino Date: Tue, 22 Sep 2026 10:17:30 +0800 Subject: [PATCH] Fix Card Drag preview on TFM --- Frameworks/Resources/Localizable.xcstrings | 448 +++++++++++++++------ TFM/UI/Managed/ManagedCardPage.swift | 6 + 2 files changed, 336 insertions(+), 118 deletions(-) diff --git a/Frameworks/Resources/Localizable.xcstrings b/Frameworks/Resources/Localizable.xcstrings index 17ca47a9..722bb67a 100644 --- a/Frameworks/Resources/Localizable.xcstrings +++ b/Frameworks/Resources/Localizable.xcstrings @@ -1,111 +1,6 @@ { "sourceLanguage" : "en", "strings" : { - "Connection Link Failed" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "连接链接失败" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "連線連結失敗" } } - } - }, - "Open Telnet Connection?" : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "打开Telnet连接?" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "開啟Telnet連線?" } } - } - }, - "SFTP text transfer mode is not supported." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "不支持SFTP文本传输模式。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "不支援SFTP文字傳輸模式。" } } - } - }, - "SSH and SFTP connection links cannot contain passwords." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "SSH和SFTP连接链接不能包含密码。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "SSH和SFTP連線連結不能包含密碼。" } } - } - }, - "The legacy fingerprint in the link matches this host key." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "链接中的旧版指纹与此主机密钥匹配。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "連結中的舊版指紋與此主機金鑰相符。" } } - } - }, - "The remote home directory is unavailable." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "远程主目录不可用。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "遠端個人專屬目錄無法使用。" } } - } - }, - "The SFTP link requires a directory, but its path is a file." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "SFTP链接要求目录,但路径指向文件。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "SFTP連結要求目錄,但路徑指向檔案。" } } - } - }, - "This connection link contains an invalid host-key fingerprint." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接包含无效的主机密钥指纹。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結包含無效的主機金鑰指紋。" } } - } - }, - "This connection link contains an unsupported standard parameter." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接包含不支持的标准参数。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結包含不支援的標準參數。" } } - } - }, - "This connection link does not contain a valid host." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接未包含有效的主机。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結未包含有效的主機。" } } - } - }, - "This connection link does not contain a valid port." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接未包含有效的端口。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結未包含有效的連接埠。" } } - } - }, - "This connection link is invalid." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接无效。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結無效。" } } - } - }, - "This connection link uses an unsupported protocol." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此连接链接使用了不支持的协议。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連線連結使用了不支援的通訊協定。" } } - } - }, - "This link includes an advisory Telnet password. It will be used once and will not be saved." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此链接包含建议的Telnet密码。该密码仅使用一次且不会保存。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此連結包含建議的Telnet密碼。該密碼僅使用一次且不會儲存。" } } - } - }, - "This remote file may contain executable content. Review it before opening." : { - "extractionState" : "manual", - "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "此远程文件可能包含可执行内容。请检查后再打开。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "此遠端檔案可能包含可執行內容。請檢查後再開啟。" } } - } - }, "" : { "localizations" : { "zh-Hans" : { @@ -6327,6 +6222,23 @@ } } }, + "Connection Link Failed" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "连接链接失败" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "連線連結失敗" + } + } + } + }, "Connection Log" : { "localizations" : { "zh-Hans" : { @@ -9901,8 +9813,18 @@ "comment" : "Error message when the user has not specified a Telnet destination.", "isCommentAutoGenerated" : true, "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "请输入Telnet目标。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "請輸入Telnet目標。" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请输入Telnet目标。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "請輸入Telnet目標。" + } + } } }, "Enter a valid project and location to configure Vertex AI." : { @@ -9943,8 +9865,18 @@ "comment" : "Error message when the username is missing.", "isCommentAutoGenerated" : true, "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "请输入-l的值。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "請輸入-l的值。" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请输入-l的值。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "請輸入-l的值。" + } + } } }, "Enter a value for %@." : { @@ -13441,16 +13373,36 @@ "comment" : "Error message when a username is specified but is empty.", "isCommentAutoGenerated" : true, "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "无效的Telnet目标。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "無效的Telnet目標。" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无效的Telnet目标。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "無效的Telnet目標。" + } + } } }, "Invalid Telnet port." : { "comment" : "Error message displayed when the Telnet port is invalid.", "isCommentAutoGenerated" : true, "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "无效的Telnet端口。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "無效的Telnet連接埠。" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无效的Telnet端口。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "無效的Telnet連接埠。" + } + } } }, "IOPS" : { @@ -17470,6 +17422,23 @@ } } }, + "Open Telnet Connection?" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开Telnet连接?" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "開啟Telnet連線?" + } + } + } + }, "Open Terminal" : { "comment" : "Opens a terminal.", "isCommentAutoGenerated" : true, @@ -19218,6 +19187,7 @@ } }, "Protocol Profile" : { + "extractionState" : "stale", "localizations" : { "zh-Hans" : { "stringUnit" : { @@ -19316,6 +19286,7 @@ } }, "Proxy for %@" : { + "extractionState" : "stale", "localizations" : { "zh-Hans" : { "stringUnit" : { @@ -22708,8 +22679,18 @@ }, "Session" : { "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "会话" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "工作階段" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "会话" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "工作階段" + } + } } }, "Set baud rate" : { @@ -22809,6 +22790,23 @@ } } }, + "SFTP text transfer mode is not supported." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "不支持SFTP文本传输模式。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "不支援SFTP文字傳輸模式。" + } + } + } + }, "SHA-256" : { "extractionState" : "stale", "localizations" : { @@ -23901,6 +23899,23 @@ } } }, + "SSH and SFTP connection links cannot contain passwords." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "SSH和SFTP连接链接不能包含密码。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "SSH和SFTP連線連結不能包含密碼。" + } + } + } + }, "SSH and SFTP, with an assistant at hand." : { "localizations" : { "zh-Hans" : { @@ -26247,6 +26262,23 @@ } } }, + "The legacy fingerprint in the link matches this host key." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "链接中的旧版指纹与此主机密钥匹配。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "連結中的舊版指紋與此主機金鑰相符。" + } + } + } + }, "The local data store could not be opened. Please restart the app." : { "localizations" : { "zh-Hans" : { @@ -26622,6 +26654,23 @@ } } }, + "The remote home directory is unavailable." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "远程主目录不可用。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "遠端個人專屬目錄無法使用。" + } + } + } + }, "The remote shell did not return its current input." : { "extractionState" : "stale", "localizations" : { @@ -27091,6 +27140,23 @@ } } }, + "The SFTP link requires a directory, but its path is a file." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "SFTP链接要求目录,但路径指向文件。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "SFTP連結要求目錄,但路徑指向檔案。" + } + } + } + }, "The SOCKS5 proxy rejected authentication." : { "extractionState" : "stale", "localizations" : { @@ -27596,6 +27662,108 @@ } } }, + "This connection link contains an invalid host-key fingerprint." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接包含无效的主机密钥指纹。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結包含無效的主機金鑰指紋。" + } + } + } + }, + "This connection link contains an unsupported standard parameter." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接包含不支持的标准参数。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結包含不支援的標準參數。" + } + } + } + }, + "This connection link does not contain a valid host." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接未包含有效的主机。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結未包含有效的主機。" + } + } + } + }, + "This connection link does not contain a valid port." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接未包含有效的端口。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結未包含有效的連接埠。" + } + } + } + }, + "This connection link is invalid." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接无效。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結無效。" + } + } + } + }, + "This connection link uses an unsupported protocol." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此连接链接使用了不支持的协议。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連線連結使用了不支援的通訊協定。" + } + } + } + }, "This Device" : { "extractionState" : "manual", "localizations" : { @@ -27777,6 +27945,23 @@ } } }, + "This link includes an advisory Telnet password. It will be used once and will not be saved." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此链接包含建议的Telnet密码。该密码仅使用一次且不会保存。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此連結包含建議的Telnet密碼。該密碼僅使用一次且不會儲存。" + } + } + } + }, "This Mac" : { "localizations" : { "zh-Hans" : { @@ -27956,6 +28141,23 @@ } } }, + "This remote file may contain executable content. Review it before opening." : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "此远程文件可能包含可执行内容。请检查后再打开。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "此遠端檔案可能包含可執行內容。請檢查後再開啟。" + } + } + } + }, "This run was interrupted and was not resumed." : { "localizations" : { "zh-Hans" : { @@ -29327,8 +29529,18 @@ "comment" : "A description of an invalid Telnet option.", "isCommentAutoGenerated" : true, "localizations" : { - "zh-Hans" : { "stringUnit" : { "state" : "translated", "value" : "不支持的Telnet选项:%@。" } }, - "zh-Hant" : { "stringUnit" : { "state" : "translated", "value" : "不支援的Telnet選項:%@。" } } + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "不支持的Telnet选项:%@。" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "不支援的Telnet選項:%@。" + } + } } }, "Up Arrow" : { @@ -31165,4 +31377,4 @@ } }, "version" : "1.2" -} +} \ No newline at end of file diff --git a/TFM/UI/Managed/ManagedCardPage.swift b/TFM/UI/Managed/ManagedCardPage.swift index 27915875..dc5dea3f 100644 --- a/TFM/UI/Managed/ManagedCardPage.swift +++ b/TFM/UI/Managed/ManagedCardPage.swift @@ -126,6 +126,8 @@ protocol ManagedCardPage: View { @ViewBuilder func managedHeader( for section: ManagedCardSection, isDropTarget: Bool ) -> HeaderContent + /// The card-shaped drag preview, reused as the destination slot while the + /// surrounding grid reflows around the dragged items. @ViewBuilder func managedGhost(for item: Item) -> GhostContent /// What right-clicking the canvas offers, given the section the pointer is /// over — nil when it is past the last one. @@ -349,6 +351,10 @@ struct ManagedCardPageRenderer: View { card.onDrag { beginDrag(from: item, in: section) return NSItemProvider(object: String(describing: item.id) as NSString) + } preview: { + // Supplying the preview avoids macOS 27's oversized prohibited + // operation badge in the default snapshot of the glass card. + ghost(item) } } else { card