diff --git a/lib/data/provider/sftp.dart b/lib/data/provider/sftp.dart index 8943289b..ca3ae4ba 100644 --- a/lib/data/provider/sftp.dart +++ b/lib/data/provider/sftp.dart @@ -14,11 +14,7 @@ class SftpProvider extends Provider { } static int add(SftpReq req, {Completer? completer}) { - final reqStat = SftpReqStatus( - notifyListeners: status.notify, - completer: completer, - req: req, - ); + final reqStat = SftpReqStatus(notifyListeners: status.notify, completer: completer, req: req); status.value.add(reqStat); status.notify(); return reqStat.id; @@ -34,6 +30,10 @@ class SftpProvider extends Provider { static void cancel(int id) { final idx = status.value.indexWhere((e) => e.id == id); + if (idx < 0 || idx >= status.value.length) { + dprint('SftpProvider.cancel: id $id not found'); + return; + } status.value[idx].dispose(); status.value.removeAt(idx); status.notify(); diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 92772430..6b0c9169 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -73,14 +73,20 @@ class SettingStore extends HiveStore { late final locale = propertyDefault('locale', ''); // SSH virtual key (ctrl | alt) auto turn off - late final sshVirtualKeyAutoOff = propertyDefault('sshVirtualKeyAutoOff', true); + late final sshVirtualKeyAutoOff = propertyDefault( + 'sshVirtualKeyAutoOff', + true, + ); late final editorFontSize = propertyDefault('editorFontSize', 12.5); // Editor theme late final editorTheme = propertyDefault('editorTheme', Defaults.editorTheme); - late final editorDarkTheme = propertyDefault('editorDarkTheme', Defaults.editorDarkTheme); + late final editorDarkTheme = propertyDefault( + 'editorDarkTheme', + Defaults.editorDarkTheme, + ); late final fullScreen = propertyDefault('fullScreen', false); @@ -110,20 +116,29 @@ class SettingStore extends HiveStore { ); // Only valid on iOS - late final autoUpdateHomeWidget = propertyDefault('autoUpdateHomeWidget', isIOS); + late final autoUpdateHomeWidget = propertyDefault( + 'autoUpdateHomeWidget', + isIOS, + ); late final autoCheckAppUpdate = propertyDefault('autoCheckAppUpdate', true); /// Display server tab function buttons on the bottom of each server card if [true] /// /// Otherwise, display them on the top of server detail page - late final moveServerFuncs = propertyDefault('moveOutServerTabFuncBtns', false); + late final moveServerFuncs = propertyDefault( + 'moveOutServerTabFuncBtns', + false, + ); /// Whether use `rm -r` to delete directory on SFTP late final sftpRmrDir = propertyDefault('sftpRmrDir', false); /// Whether use system's primary color as the app's primary color - late final useSystemPrimaryColor = propertyDefault('useSystemPrimaryColor', false); + late final useSystemPrimaryColor = propertyDefault( + 'useSystemPrimaryColor', + false, + ); /// Only valid on iOS / Android / Windows late final useBioAuth = propertyDefault('useBioAuth', false); @@ -135,7 +150,10 @@ class SettingStore extends HiveStore { late final sftpOpenLastPath = propertyDefault('sftpOpenLastPath', true); /// Show folders first in SFTP file browser - late final sftpShowFoldersFirst = propertyDefault('sftpShowFoldersFirst', true); + late final sftpShowFoldersFirst = propertyDefault( + 'sftpShowFoldersFirst', + true, + ); /// Show tip of suspend late final showSuspendTip = propertyDefault('showSuspendTip', true); @@ -161,7 +179,10 @@ class SettingStore extends HiveStore { late final containerParseStat = propertyDefault('containerParseStat', true); /// Auto refresh container status - late final contaienrAutoRefresh = propertyDefault('contaienrAutoRefresh', true); + late final contaienrAutoRefresh = propertyDefault( + 'contaienrAutoRefresh', + true, + ); /// Use double column servers page on Desktop late final doubleColumnServersPage = propertyDefault( @@ -219,7 +240,8 @@ class SettingStore extends HiveStore { /// Record the position and size of the window. late final windowState = property( 'windowState', - fromObj: (raw) => WindowState.fromJson(jsonDecode(raw as String) as Map), + fromObj: (raw) => + WindowState.fromJson(jsonDecode(raw as String) as Map), toObj: (state) => state == null ? null : jsonEncode(state.toJson()), ); @@ -231,6 +253,12 @@ class SettingStore extends HiveStore { /// Set it empty to use local editor GUI. late final sftpEditor = propertyDefault('sftpEditor', ''); + /// Preferred terminal emulator command on desktop + late final desktopTerminal = propertyDefault( + 'desktopTerminal', + 'x-terminal-emulator', + ); + /// Run foreground service on Android, if the SSH terminal is running late final fgService = propertyDefault('fgService', false); diff --git a/lib/generated/l10n/l10n.dart b/lib/generated/l10n/l10n.dart index 46f7a57c..bb3f8db6 100644 --- a/lib/generated/l10n/l10n.dart +++ b/lib/generated/l10n/l10n.dart @@ -311,6 +311,12 @@ abstract class AppLocalizations { /// **'Batch delete servers'** String get deleteServers; + /// No description provided for @desktopTerminalTip. + /// + /// In en, this message translates to: + /// **'Command used to open the terminal emulator when launching SSH sessions.'** + String get desktopTerminalTip; + /// No description provided for @dirEmpty. /// /// In en, this message translates to: @@ -410,6 +416,12 @@ abstract class AppLocalizations { /// **'The current code highlighting performance is not ideal and can be optionally turned off to improve.'** String get editorHighlightTip; + /// No description provided for @emulator. + /// + /// In en, this message translates to: + /// **'Emulator'** + String get emulator; + /// No description provided for @encode. /// /// In en, this message translates to: diff --git a/lib/generated/l10n/l10n_de.dart b/lib/generated/l10n/l10n_de.dart index b7a9be93..a720f3b4 100644 --- a/lib/generated/l10n/l10n_de.dart +++ b/lib/generated/l10n/l10n_de.dart @@ -115,6 +115,10 @@ class AppLocalizationsDe extends AppLocalizations { @override String get deleteServers => 'Batch-Löschung von Servern'; + @override + String get desktopTerminalTip => + 'Befehl zum Öffnen des Terminal-Emulators beim Starten von SSH-Sitzungen.'; + @override String get dirEmpty => 'Stelle sicher, dass der Ordner leer ist.'; @@ -177,6 +181,9 @@ class AppLocalizationsDe extends AppLocalizations { String get editorHighlightTip => 'Die Leistung der aktuellen Codehervorhebung ist schlechter und kann zur Verbesserung optional ausgeschaltet werden.'; + @override + String get emulator => 'Emulator'; + @override String get encode => 'Encode'; diff --git a/lib/generated/l10n/l10n_en.dart b/lib/generated/l10n/l10n_en.dart index b9c1b908..6533860f 100644 --- a/lib/generated/l10n/l10n_en.dart +++ b/lib/generated/l10n/l10n_en.dart @@ -114,6 +114,10 @@ class AppLocalizationsEn extends AppLocalizations { @override String get deleteServers => 'Batch delete servers'; + @override + String get desktopTerminalTip => + 'Command used to open the terminal emulator when launching SSH sessions.'; + @override String get dirEmpty => 'Make sure the folder is empty.'; @@ -176,6 +180,9 @@ class AppLocalizationsEn extends AppLocalizations { String get editorHighlightTip => 'The current code highlighting performance is not ideal and can be optionally turned off to improve.'; + @override + String get emulator => 'Emulator'; + @override String get encode => 'Encode'; diff --git a/lib/generated/l10n/l10n_es.dart b/lib/generated/l10n/l10n_es.dart index 0af62617..c04e78e2 100644 --- a/lib/generated/l10n/l10n_es.dart +++ b/lib/generated/l10n/l10n_es.dart @@ -115,6 +115,10 @@ class AppLocalizationsEs extends AppLocalizations { @override String get deleteServers => 'Eliminar servidores en lote'; + @override + String get desktopTerminalTip => + 'Comando utilizado para abrir el emulador de terminal al iniciar sesiones SSH.'; + @override String get dirEmpty => 'Asegúrate de que el directorio esté vacío'; @@ -177,6 +181,9 @@ class AppLocalizationsEs extends AppLocalizations { String get editorHighlightTip => 'El rendimiento del resaltado de código es bastante pobre actualmente, puedes elegir desactivarlo para mejorar.'; + @override + String get emulator => 'Emulador'; + @override String get encode => 'Codificar'; diff --git a/lib/generated/l10n/l10n_fr.dart b/lib/generated/l10n/l10n_fr.dart index 9793cdd1..fb1152c0 100644 --- a/lib/generated/l10n/l10n_fr.dart +++ b/lib/generated/l10n/l10n_fr.dart @@ -115,6 +115,10 @@ class AppLocalizationsFr extends AppLocalizations { @override String get deleteServers => 'Supprimer des serveurs en lot'; + @override + String get desktopTerminalTip => + 'Commande utilisée pour ouvrir l’émulateur de terminal lors du lancement de sessions SSH.'; + @override String get dirEmpty => 'Assurez-vous que le répertoire est vide.'; @@ -177,6 +181,9 @@ class AppLocalizationsFr extends AppLocalizations { String get editorHighlightTip => 'La performance actuelle de mise en surbrillance du code est pire et peut être désactivée en option pour s\'améliorer.'; + @override + String get emulator => 'Émulateur'; + @override String get encode => 'Encoder'; diff --git a/lib/generated/l10n/l10n_id.dart b/lib/generated/l10n/l10n_id.dart index 1457499d..e55ec657 100644 --- a/lib/generated/l10n/l10n_id.dart +++ b/lib/generated/l10n/l10n_id.dart @@ -114,6 +114,10 @@ class AppLocalizationsId extends AppLocalizations { @override String get deleteServers => 'Penghapusan server secara batch'; + @override + String get desktopTerminalTip => + 'Perintah yang digunakan untuk membuka emulator terminal saat memulai sesi SSH.'; + @override String get dirEmpty => 'Pastikan dir kosong.'; @@ -176,6 +180,9 @@ class AppLocalizationsId extends AppLocalizations { String get editorHighlightTip => 'Performa penyorotan kode saat ini lebih buruk, dan dapat dimatikan secara opsional untuk perbaikan.'; + @override + String get emulator => 'Emulator'; + @override String get encode => 'Menyandi'; diff --git a/lib/generated/l10n/l10n_ja.dart b/lib/generated/l10n/l10n_ja.dart index 1fbc2387..96be5328 100644 --- a/lib/generated/l10n/l10n_ja.dart +++ b/lib/generated/l10n/l10n_ja.dart @@ -108,6 +108,9 @@ class AppLocalizationsJa extends AppLocalizations { @override String get deleteServers => 'サーバーを一括削除'; + @override + String get desktopTerminalTip => 'SSHセッションを起動する際に使用されるターミナルエミュレーターを開くコマンド。'; + @override String get dirEmpty => 'フォルダーが空であることを確認してください'; @@ -170,6 +173,9 @@ class AppLocalizationsJa extends AppLocalizations { String get editorHighlightTip => '現在のコードハイライトのパフォーマンスはかなり悪いため、改善するために無効にすることを選択できます。'; + @override + String get emulator => 'エミュレーター'; + @override String get encode => 'エンコード'; diff --git a/lib/generated/l10n/l10n_nl.dart b/lib/generated/l10n/l10n_nl.dart index beebc1e9..6a172f5c 100644 --- a/lib/generated/l10n/l10n_nl.dart +++ b/lib/generated/l10n/l10n_nl.dart @@ -114,6 +114,10 @@ class AppLocalizationsNl extends AppLocalizations { @override String get deleteServers => 'Servers batchgewijs verwijderen'; + @override + String get desktopTerminalTip => + 'Opdracht die wordt gebruikt om de terminalemulator te openen bij het starten van SSH-sessies.'; + @override String get dirEmpty => 'Zorg ervoor dat de map leeg is.'; @@ -176,6 +180,9 @@ class AppLocalizationsNl extends AppLocalizations { String get editorHighlightTip => 'De huidige codehighlighting-prestaties zijn slechter en kunnen optioneel worden uitgeschakeld om te verbeteren.'; + @override + String get emulator => 'Emulator'; + @override String get encode => 'Coderen'; diff --git a/lib/generated/l10n/l10n_pt.dart b/lib/generated/l10n/l10n_pt.dart index d7f10fe2..56e4a2a7 100644 --- a/lib/generated/l10n/l10n_pt.dart +++ b/lib/generated/l10n/l10n_pt.dart @@ -114,6 +114,10 @@ class AppLocalizationsPt extends AppLocalizations { @override String get deleteServers => 'Excluir servidores em lote'; + @override + String get desktopTerminalTip => + 'Comando usado para abrir o emulador de terminal ao iniciar sessões SSH.'; + @override String get dirEmpty => 'Certifique-se de que a pasta está vazia'; @@ -176,6 +180,9 @@ class AppLocalizationsPt extends AppLocalizations { String get editorHighlightTip => 'O desempenho do destaque de código atualmente é ruim, pode optar por desativá-lo para melhorar.'; + @override + String get emulator => 'Emulador'; + @override String get encode => 'Codificar'; diff --git a/lib/generated/l10n/l10n_ru.dart b/lib/generated/l10n/l10n_ru.dart index 1924aacd..1d3e0d8f 100644 --- a/lib/generated/l10n/l10n_ru.dart +++ b/lib/generated/l10n/l10n_ru.dart @@ -114,6 +114,10 @@ class AppLocalizationsRu extends AppLocalizations { @override String get deleteServers => 'Удалить серверы пакетно'; + @override + String get desktopTerminalTip => + 'Команда для открытия эмулятора терминала при запуске SSH-сеансов.'; + @override String get dirEmpty => 'Пожалуйста, убедитесь, что папка пуста'; @@ -176,6 +180,9 @@ class AppLocalizationsRu extends AppLocalizations { String get editorHighlightTip => 'Текущая производительность подсветки кода неудовлетворительна, можно отключить для улучшения.'; + @override + String get emulator => 'Эмулятор'; + @override String get encode => 'Кодировать'; diff --git a/lib/generated/l10n/l10n_tr.dart b/lib/generated/l10n/l10n_tr.dart index 3b81f4c4..15ccd30c 100644 --- a/lib/generated/l10n/l10n_tr.dart +++ b/lib/generated/l10n/l10n_tr.dart @@ -113,6 +113,10 @@ class AppLocalizationsTr extends AppLocalizations { @override String get deleteServers => 'Sunucuları toplu sil'; + @override + String get desktopTerminalTip => + 'SSH oturumları başlatılırken terminal öykünücüsünü açmak için kullanılan komut.'; + @override String get dirEmpty => 'Klasörün boş olduğundan emin olun.'; @@ -175,6 +179,9 @@ class AppLocalizationsTr extends AppLocalizations { String get editorHighlightTip => 'Mevcut kod vurgulama performansı ideal değil ve isteğe bağlı olarak kapatılabilir.'; + @override + String get emulator => 'Emülatör'; + @override String get encode => 'Kodla'; diff --git a/lib/generated/l10n/l10n_uk.dart b/lib/generated/l10n/l10n_uk.dart index 1e8308f4..daf42f57 100644 --- a/lib/generated/l10n/l10n_uk.dart +++ b/lib/generated/l10n/l10n_uk.dart @@ -115,6 +115,10 @@ class AppLocalizationsUk extends AppLocalizations { @override String get deleteServers => 'Масове видалення серверів'; + @override + String get desktopTerminalTip => + 'Команда для відкриття емулятора термінала під час запуску SSH-сеансів.'; + @override String get dirEmpty => 'Переконайтеся, що директорія пуста.'; @@ -177,6 +181,9 @@ class AppLocalizationsUk extends AppLocalizations { String get editorHighlightTip => 'Поточна підсвітка коду не ідеальна і може бути вимкнена для покращення.'; + @override + String get emulator => 'Емулятор'; + @override String get encode => 'Кодувати'; diff --git a/lib/generated/l10n/l10n_zh.dart b/lib/generated/l10n/l10n_zh.dart index bdce41ca..37d5d17d 100644 --- a/lib/generated/l10n/l10n_zh.dart +++ b/lib/generated/l10n/l10n_zh.dart @@ -107,6 +107,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get deleteServers => '批量删除服务器'; + @override + String get desktopTerminalTip => '启动 SSH 连接所用的终端模拟器命令'; + @override String get dirEmpty => '请确保文件夹为空'; @@ -167,6 +170,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get editorHighlightTip => '目前的代码高亮性能较为糟糕,可以选择关闭以改善。'; + @override + String get emulator => '模拟器'; + @override String get encode => '编码'; @@ -826,6 +832,9 @@ class AppLocalizationsZhTw extends AppLocalizationsZh { @override String get deleteServers => '批量刪除伺服器'; + @override + String get desktopTerminalTip => '啟動 SSH 連線時用於打開終端機模擬器的指令。'; + @override String get dirEmpty => '請確保資料夾為空'; @@ -886,6 +895,9 @@ class AppLocalizationsZhTw extends AppLocalizationsZh { @override String get editorHighlightTip => '目前的代碼高亮性能較為糟糕,可以選擇關閉以改善。'; + @override + String get emulator => '模擬器'; + @override String get encode => '編碼'; diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 76d60134..fe3a7ece 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -32,6 +32,7 @@ "decode": "Decode", "decompress": "Dekomprimieren", "deleteServers": "Batch-Löschung von Servern", + "desktopTerminalTip": "Befehl zum Öffnen des Terminal-Emulators beim Starten von SSH-Sitzungen.", "dirEmpty": "Stelle sicher, dass der Ordner leer ist.", "disconnected": "Disconnected", "disk": "Festplatte", @@ -48,6 +49,7 @@ "editVirtKeys": "Virtuelle Tasten bearbeiten", "editor": "Editor", "editorHighlightTip": "Die Leistung der aktuellen Codehervorhebung ist schlechter und kann zur Verbesserung optional ausgeschaltet werden.", + "emulator": "Emulator", "encode": "Encode", "envVars": "Umgebungsvariable", "experimentalFeature": "Experimentelles Feature", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e1817e81..8bc20b77 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -32,6 +32,7 @@ "decode": "Decode", "decompress": "Decompress", "deleteServers": "Batch delete servers", + "desktopTerminalTip": "Command used to open the terminal emulator when launching SSH sessions.", "dirEmpty": "Make sure the folder is empty.", "disconnected": "Disconnected", "disk": "Disk", @@ -48,6 +49,7 @@ "editVirtKeys": "Edit virtual keys", "editor": "Editor", "editorHighlightTip": "The current code highlighting performance is not ideal and can be optionally turned off to improve.", + "emulator": "Emulator", "encode": "Encode", "envVars": "Environment variable", "experimentalFeature": "Experimental feature", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 66049009..8f17d026 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -32,6 +32,7 @@ "decode": "Decodificar", "decompress": "Descomprimir", "deleteServers": "Eliminar servidores en lote", + "desktopTerminalTip": "Comando utilizado para abrir el emulador de terminal al iniciar sesiones SSH.", "dirEmpty": "Asegúrate de que el directorio esté vacío", "disconnected": "Desconectado", "disk": "Disco", @@ -48,6 +49,7 @@ "editVirtKeys": "Editar teclas virtuales", "editor": "Editor", "editorHighlightTip": "El rendimiento del resaltado de código es bastante pobre actualmente, puedes elegir desactivarlo para mejorar.", + "emulator": "Emulador", "encode": "Codificar", "envVars": "Variable de entorno", "experimentalFeature": "Función experimental", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 49e1b60b..769576cf 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -32,6 +32,7 @@ "decode": "Décoder", "decompress": "Décompresser", "deleteServers": "Supprimer des serveurs en lot", + "desktopTerminalTip": "Commande utilisée pour ouvrir l’émulateur de terminal lors du lancement de sessions SSH.", "dirEmpty": "Assurez-vous que le répertoire est vide.", "disconnected": "Déconnecté", "disk": "Disque", @@ -48,6 +49,7 @@ "editVirtKeys": "Modifier les touches virtuelles", "editor": "Éditeur", "editorHighlightTip": "La performance actuelle de mise en surbrillance du code est pire et peut être désactivée en option pour s'améliorer.", + "emulator": "Émulateur", "encode": "Encoder", "envVars": "Variable d’environnement", "experimentalFeature": "Fonctionnalité expérimentale", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 78158478..b2d5f24d 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -32,6 +32,7 @@ "decode": "Membaca sandi", "decompress": "Dekompresi", "deleteServers": "Penghapusan server secara batch", + "desktopTerminalTip": "Perintah yang digunakan untuk membuka emulator terminal saat memulai sesi SSH.", "dirEmpty": "Pastikan dir kosong.", "disconnected": "Terputus", "disk": "Disk", @@ -48,6 +49,7 @@ "editVirtKeys": "Edit kunci virtual", "editor": "Editor", "editorHighlightTip": "Performa penyorotan kode saat ini lebih buruk, dan dapat dimatikan secara opsional untuk perbaikan.", + "emulator": "Emulator", "encode": "Menyandi", "envVars": "Variabel lingkungan", "experimentalFeature": "Fitur eksperimental", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index f78eabc5..eccade00 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -32,6 +32,7 @@ "decode": "デコード", "decompress": "解凍", "deleteServers": "サーバーを一括削除", + "desktopTerminalTip": "SSHセッションを起動する際に使用されるターミナルエミュレーターを開くコマンド。", "dirEmpty": "フォルダーが空であることを確認してください", "disconnected": "接続が切断されました", "disk": "ディスク", @@ -48,6 +49,7 @@ "editVirtKeys": "仮想キーを編集", "editor": "エディター", "editorHighlightTip": "現在のコードハイライトのパフォーマンスはかなり悪いため、改善するために無効にすることを選択できます。", + "emulator": "エミュレーター", "encode": "エンコード", "envVars": "環境変数", "experimentalFeature": "実験的な機能", diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index d1ff8319..1f6b8ac9 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -32,6 +32,7 @@ "decode": "Decoderen", "decompress": "Decomprimeren", "deleteServers": "Servers batchgewijs verwijderen", + "desktopTerminalTip": "Opdracht die wordt gebruikt om de terminalemulator te openen bij het starten van SSH-sessies.", "dirEmpty": "Zorg ervoor dat de map leeg is.", "disconnected": "Verbroken", "disk": "Schijf", @@ -48,6 +49,7 @@ "editVirtKeys": "Virtuele toetsen bewerken", "editor": "Editor", "editorHighlightTip": "De huidige codehighlighting-prestaties zijn slechter en kunnen optioneel worden uitgeschakeld om te verbeteren.", + "emulator": "Emulator", "encode": "Coderen", "envVars": "Omgevingsvariabele", "experimentalFeature": "Experimentele functie", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index c21aa033..aef304ac 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -32,6 +32,7 @@ "decode": "Decodificar", "decompress": "Descomprimir", "deleteServers": "Excluir servidores em lote", + "desktopTerminalTip": "Comando usado para abrir o emulador de terminal ao iniciar sessões SSH.", "dirEmpty": "Certifique-se de que a pasta está vazia", "disconnected": "Desconectado", "disk": "Disco", @@ -48,6 +49,7 @@ "editVirtKeys": "Editar teclas virtuais", "editor": "Editor", "editorHighlightTip": "O desempenho do destaque de código atualmente é ruim, pode optar por desativá-lo para melhorar.", + "emulator": "Emulador", "encode": "Codificar", "envVars": "Variável de ambiente", "experimentalFeature": "Recurso experimental", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 000f0156..886a197e 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -32,6 +32,7 @@ "decode": "Декодировать", "decompress": "Разархивировать", "deleteServers": "Удалить серверы пакетно", + "desktopTerminalTip": "Команда для открытия эмулятора терминала при запуске SSH-сеансов.", "dirEmpty": "Пожалуйста, убедитесь, что папка пуста", "disconnected": "Отключено", "disk": "Диск", @@ -48,6 +49,7 @@ "editVirtKeys": "Редактировать виртуальные клавиши", "editor": "Редактор", "editorHighlightTip": "Текущая производительность подсветки кода неудовлетворительна, можно отключить для улучшения.", + "emulator": "Эмулятор", "encode": "Кодировать", "envVars": "Переменная окружения", "experimentalFeature": "Экспериментальная функция", diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index d9335e45..469556b2 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -32,6 +32,7 @@ "decode": "Çöz", "decompress": "Sıkıştırmayı aç", "deleteServers": "Sunucuları toplu sil", + "desktopTerminalTip": "SSH oturumları başlatılırken terminal öykünücüsünü açmak için kullanılan komut.", "dirEmpty": "Klasörün boş olduğundan emin olun.", "disconnected": "Bağlantı kesildi", "disk": "Disk", @@ -48,6 +49,7 @@ "editVirtKeys": "Sanal tuşları düzenle", "editor": "Düzenleyici", "editorHighlightTip": "Mevcut kod vurgulama performansı ideal değil ve isteğe bağlı olarak kapatılabilir.", + "emulator": "Emülatör", "encode": "Kodla", "envVars": "Ortam değişkeni", "experimentalFeature": "Deneysel özellik", @@ -226,4 +228,4 @@ "write": "Yaz", "writeScriptFailTip": "Betik yazma başarısız oldu, muhtemelen izin eksikliği veya dizin mevcut değil.", "writeScriptTip": "Sunucuya bağlandıktan sonra, sistem durumunu izlemek için ~/.config/server_box dizinine bir betik yazılacak. Betik içeriğini inceleyebilirsiniz." -} +} \ No newline at end of file diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index 6c2e7569..3a9da383 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -32,6 +32,7 @@ "decode": "Декодувати", "decompress": "Розпакувати", "deleteServers": "Масове видалення серверів", + "desktopTerminalTip": "Команда для відкриття емулятора термінала під час запуску SSH-сеансів.", "dirEmpty": "Переконайтеся, що директорія пуста.", "disconnected": "Відключено", "disk": "Диск", @@ -48,6 +49,7 @@ "editVirtKeys": "Редагувати віртуальні клавіші", "editor": "Редактор", "editorHighlightTip": "Поточна підсвітка коду не ідеальна і може бути вимкнена для покращення.", + "emulator": "Емулятор", "encode": "Кодувати", "envVars": "Змінні середовища", "experimentalFeature": "Експериментальна функція", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 37ef674b..1bcf220b 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -32,6 +32,7 @@ "decode": "解码", "decompress": "解压缩", "deleteServers": "批量删除服务器", + "desktopTerminalTip": "启动 SSH 连接所用的终端模拟器命令", "dirEmpty": "请确保文件夹为空", "disconnected": "连接断开", "disk": "磁盘", @@ -48,6 +49,7 @@ "editVirtKeys": "编辑虚拟按键", "editor": "编辑器", "editorHighlightTip": "目前的代码高亮性能较为糟糕,可以选择关闭以改善。", + "emulator": "模拟器", "encode": "编码", "envVars": "环境变量", "experimentalFeature": "实验性功能", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 38daa83d..775b0f3d 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -32,6 +32,7 @@ "decode": "解碼", "decompress": "解壓縮", "deleteServers": "批量刪除伺服器", + "desktopTerminalTip": "啟動 SSH 連線時用於打開終端機模擬器的指令。", "dirEmpty": "請確保資料夾為空", "disconnected": "連接斷開", "disk": "磁碟", @@ -48,6 +49,7 @@ "editVirtKeys": "編輯虛擬按鍵", "editor": "編輯器", "editorHighlightTip": "目前的代碼高亮性能較為糟糕,可以選擇關閉以改善。", + "emulator": "模擬器", "encode": "編碼", "envVars": "環境變量", "experimentalFeature": "實驗性功能", diff --git a/lib/view/page/setting/entries/ssh.dart b/lib/view/page/setting/entries/ssh.dart index 01662657..14dceb8d 100644 --- a/lib/view/page/setting/entries/ssh.dart +++ b/lib/view/page/setting/entries/ssh.dart @@ -9,6 +9,7 @@ extension _SSH on _AppSettingsPageState { _buildTermTheme(), _buildFont(), _buildTermFontSize(), + if (isDesktop) _buildDesktopTerminal(), _buildSSHVirtualKeyAutoOff(), if (isMobile) _buildSSHVirtKeys(), ].map((e) => CardX(child: e)).toList(), @@ -37,15 +38,10 @@ extension _SSH on _AppSettingsPageState { return ListTile( leading: const Icon(MingCute.font_fill), title: Text(l10n.font), - trailing: _setting.fontPath.listenable().listenVal( - (val) { - final fontName = val.getFileName(); - return Text( - fontName ?? libL10n.empty, - style: UIs.text15, - ); - }, - ), + trailing: _setting.fontPath.listenable().listenVal((val) { + final fontName = val.getFileName(); + return Text(fontName ?? libL10n.empty, style: UIs.text15); + }), onTap: () { context.showRoundDialog( title: l10n.font, @@ -61,7 +57,7 @@ extension _SSH on _AppSettingsPageState { RNodes.app.notify(); }, child: Text(libL10n.clear), - ) + ), ], ); }, @@ -85,6 +81,42 @@ extension _SSH on _AppSettingsPageState { RNodes.app.notify(); } + Widget _buildDesktopTerminal() { + return _setting.desktopTerminal.listenable().listenVal((val) { + return ListTile( + leading: const Icon(Icons.terminal), + title: TipText(l10n.terminal, l10n.desktopTerminalTip), + trailing: Text( + val, + style: UIs.text15, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + onTap: () async { + final ctrl = TextEditingController(text: val); + void onSave() { + _setting.desktopTerminal.put(ctrl.text.trim()); + context.pop(); + } + + context.showRoundDialog( + title: libL10n.select, + child: Input( + controller: ctrl, + autoFocus: true, + label: l10n.terminal, + hint: 'x-terminal-emulator / gnome-terminal', + icon: Icons.edit, + suggestion: false, + onSubmitted: (_) => onSave(), + ), + actions: Btn.ok(onTap: onSave).toList, + ); + }, + ); + }); + } + Widget _buildTermTheme() { String index2Str(int index) { switch (index) { @@ -104,10 +136,7 @@ extension _SSH on _AppSettingsPageState { title: Text(l10n.theme), trailing: ValBuilder( listenable: _setting.termTheme.listenable(), - builder: (val) => Text( - index2Str(val), - style: UIs.text15, - ), + builder: (val) => Text(index2Str(val), style: UIs.text15), ), onTap: () async { final selected = await context.showPickSingleDialog( @@ -140,7 +169,9 @@ extension _SSH on _AppSettingsPageState { // style: UIs.textGrey, // ), title: TipText( - l10n.letterCache, '${l10n.letterCacheTip}\n${l10n.needRestart}'), + l10n.letterCache, + '${l10n.letterCacheTip}\n${l10n.needRestart}', + ), trailing: StoreSwitch(prop: _setting.letterCache), ); } diff --git a/lib/view/widget/server_func_btns.dart b/lib/view/widget/server_func_btns.dart index f6b27859..12fd4c2a 100644 --- a/lib/view/widget/server_func_btns.dart +++ b/lib/view/widget/server_func_btns.dart @@ -22,10 +22,7 @@ import 'package:server_box/view/page/systemd.dart'; class ServerFuncBtnsTopRight extends StatelessWidget { final Spi spi; - const ServerFuncBtnsTopRight({ - super.key, - required this.spi, - }); + const ServerFuncBtnsTopRight({super.key, required this.spi}); @override Widget build(BuildContext context) { @@ -38,10 +35,7 @@ class ServerFuncBtnsTopRight extends StatelessWidget { } class ServerFuncBtns extends StatelessWidget { - const ServerFuncBtns({ - super.key, - required this.spi, - }); + const ServerFuncBtns({super.key, required this.spi}); final Spi spi; @@ -86,7 +80,7 @@ class ServerFuncBtns extends StatelessWidget { padding: EdgeInsets.zero, icon: Icon(e.icon, size: 17), ), - Text(e.toStr, style: UIs.text11Grey) + Text(e.toStr, style: UIs.text11Grey), ], ), ); @@ -107,11 +101,7 @@ class ServerFuncBtns extends StatelessWidget { } } -void _onTapMoreBtns( - ServerFuncBtn value, - Spi spi, - BuildContext context, -) async { +void _onTapMoreBtns(ServerFuncBtn value, Spi spi, BuildContext context) async { // final isMobile = ResponsiveBreakpoints.of(context).isMobile; switch (value) { // case ServerFuncBtn.pkg: @@ -153,16 +143,8 @@ void _onTapMoreBtns( final fmted = snippet.fmtWithSpi(spi); final sure = await context.showRoundDialog( title: libL10n.attention, - child: SingleChildScrollView( - child: SimpleMarkdown(data: '```shell\n$fmted\n```'), - ), - actions: [ - CountDownBtn( - onTap: () => context.pop(true), - text: l10n.run, - afterColor: Colors.red, - ), - ], + child: SingleChildScrollView(child: SimpleMarkdown(data: '```shell\n$fmted\n```')), + actions: [CountDownBtn(onTap: () => context.pop(true), text: l10n.run, afterColor: Colors.red)], ); if (sure != true) return; if (!_checkClient(context, spi.id)) return; @@ -178,13 +160,13 @@ void _onTapMoreBtns( case ServerFuncBtn.container: if (!_checkClient(context, spi.id)) return; final args = SpiRequiredArgs(spi); - if (isMobile) { - ContainerPage.route.go(context, args); - } else { - SplitViewNavigator.of(context)?.replace( - ContainerPage.route.toWidget(args: args), - ); - } + // if (isMobile) { + ContainerPage.route.go(context, args); + // } else { + // SplitViewNavigator.of( + // context, + // )?.replace(ContainerPage.route.toWidget(args: args)); + // } break; case ServerFuncBtn.process: if (!_checkClient(context, spi.id)) return; @@ -260,7 +242,23 @@ void _gotoSSH(Spi spi, BuildContext context) async { await Process.start('cmd', ['/c', 'start'] + sshCommand); break; case Pfs.linux: - await Process.start('x-terminal-emulator', ['-e'] + sshCommand); + final scriptFile = File('${Directory.systemTemp.path}/srvbox_launch_term.sh'); + await scriptFile.writeAsString(_runEmulatorShell); + + if (Platform.isLinux || Platform.isMacOS) { + await Process.run('chmod', ['+x', scriptFile.path]); + } + + try { + var terminal = Stores.setting.desktopTerminal.fetch(); + if (terminal.isEmpty) terminal = 'x-terminal-emulator'; + + await Process.start(scriptFile.path, [terminal, ...sshCommand]); + } catch (e, s) { + context.showErrDialog(e, s, l10n.emulator); + } finally { + await scriptFile.delete(); + } break; default: context.showSnackBar('Mismatch system: $system'); @@ -280,3 +278,62 @@ bool _checkClient(BuildContext context, String id) { } return true; } + +const _runEmulatorShell = ''' +#!/bin/sh +# launch_terminal.sh + +TERMINAL="\$1" +shift # Remove the first argument (terminal name) + +# Auto detect terminal if not provided +if [ -z "\$TERMINAL" ] || [ "\$TERMINAL" = "x-terminal-emulator" ]; then + # Follow the order of preference + for term in kitty alacritty gnome-terminal konsole xfce4-terminal terminator tilix wezterm foot; do + if command -v "\$term" >/dev/null 2>&1; then + TERMINAL="\$term" + break + fi + done + + [ -z "\$TERMINAL" ] && TERMINAL="x-terminal-emulator" +fi + +case "\$TERMINAL" in + gnome-terminal) + exec "\$TERMINAL" -- "\$@" + ;; + konsole|terminator|tilix) + exec "\$TERMINAL" -e "\$@" + ;; + xfce4-terminal) + exec "\$TERMINAL" -e "\$*" + ;; + alacritty) + # Check alacritty version + if "\$TERMINAL" --version 2>&1 | grep -q "alacritty 0\\.1[3-9]"; then + # 0.13.0+ + exec "\$TERMINAL" --command "\$@" + else + # Old versions + exec "\$TERMINAL" -e "\$@" + fi + ;; + kitty) + exec "\$TERMINAL" "\$@" + ;; + wezterm) + exec "\$TERMINAL" start -- "\$@" + ;; + foot) + exec "\$TERMINAL" "\$@" + ;; + urxvt|rxvt-unicode) + exec "\$TERMINAL" -e "\$@" + ;; + x-terminal-emulator|*) + # Default + exec "\$TERMINAL" -e "\$@" + ;; +esac +''';