new: auto run snippet (#67)

This commit is contained in:
lollipopkit
2024-02-18 15:00:41 +08:00
parent 8bfea497a0
commit 61ddb56639
31 changed files with 221 additions and 122 deletions

View File

@@ -202,6 +202,12 @@ abstract class S {
/// **'Auto connect'**
String get autoConnect;
/// No description provided for @autoRun.
///
/// In en, this message translates to:
/// **'Automatic Run'**
String get autoRun;
/// No description provided for @autoUpdateHomeWidget.
///
/// In en, this message translates to:
@@ -1342,18 +1348,18 @@ abstract class S {
/// **'Use `rm -r` to delete a folder in SFTP.'**
String get sftpRmrDirSummary;
/// No description provided for @sftpShowFoldersFirst.
///
/// In en, this message translates to:
/// **'Disply folders first'**
String get sftpShowFoldersFirst;
/// No description provided for @sftpSSHConnected.
///
/// In en, this message translates to:
/// **'SFTP Connected'**
String get sftpSSHConnected;
/// No description provided for @sftpShowFoldersFirst.
///
/// In en, this message translates to:
/// **'Disply folders first'**
String get sftpShowFoldersFirst;
/// No description provided for @showDistLogo.
///
/// In en, this message translates to:

View File

@@ -57,6 +57,9 @@ class SDe extends S {
@override
String get autoConnect => 'Automatisch verbinden';
@override
String get autoRun => 'Automatischer Start';
@override
String get autoUpdateHomeWidget => 'Home-Widget automatisch aktualisieren';
@@ -652,10 +655,10 @@ class SDe extends S {
String get sftpRmrDirSummary => 'Verwenden Sie \"rm -r\", um das Verzeichnis in SFTP zu löschen.';
@override
String get sftpShowFoldersFirst => 'Ordner zuerst anzeigen';
String get sftpSSHConnected => 'SFTP Verbunden';
@override
String get sftpSSHConnected => 'SFTP Verbunden';
String get sftpShowFoldersFirst => 'Ordner zuerst anzeigen';
@override
String get showDistLogo => 'Distributionslogo anzeigen';

View File

@@ -57,6 +57,9 @@ class SEn extends S {
@override
String get autoConnect => 'Auto connect';
@override
String get autoRun => 'Automatic Run';
@override
String get autoUpdateHomeWidget => 'Auto update home widget';
@@ -652,10 +655,10 @@ class SEn extends S {
String get sftpRmrDirSummary => 'Use `rm -r` to delete a folder in SFTP.';
@override
String get sftpShowFoldersFirst => 'Disply folders first';
String get sftpSSHConnected => 'SFTP Connected';
@override
String get sftpSSHConnected => 'SFTP Connected';
String get sftpShowFoldersFirst => 'Disply folders first';
@override
String get showDistLogo => 'Show distribution logo';

View File

@@ -57,6 +57,9 @@ class SFr extends S {
@override
String get autoConnect => 'Connexion automatique';
@override
String get autoRun => 'Exécution automatique';
@override
String get autoUpdateHomeWidget => 'Mise à jour automatique du widget d\'accueil';
@@ -652,10 +655,10 @@ class SFr extends S {
String get sftpRmrDirSummary => 'Utilisez `rm -r` pour supprimer un dossier dans SFTP.';
@override
String get sftpShowFoldersFirst => 'Dossiers d\'abord lors du tri';
String get sftpSSHConnected => 'SFTP connecté';
@override
String get sftpSSHConnected => 'SFTP connecté';
String get sftpShowFoldersFirst => 'Dossiers d\'abord lors du tri';
@override
String get showDistLogo => 'Afficher le logo de la distribution';

View File

@@ -57,6 +57,9 @@ class SId extends S {
@override
String get autoConnect => 'Hubungkan otomatis';
@override
String get autoRun => 'Berjalan Otomatis';
@override
String get autoUpdateHomeWidget => 'Widget Rumah Pembaruan Otomatis';
@@ -652,10 +655,10 @@ class SId extends S {
String get sftpRmrDirSummary => 'Gunakan `rm -r` untuk menghapus dir di SFTP';
@override
String get sftpShowFoldersFirst => 'Folder ditampilkan lebih dulu';
String get sftpSSHConnected => 'Sftp terhubung';
@override
String get sftpSSHConnected => 'Sftp terhubung';
String get sftpShowFoldersFirst => 'Folder ditampilkan lebih dulu';
@override
String get showDistLogo => 'Tampilkan logo distribusi';

View File

@@ -57,6 +57,9 @@ class SZh extends S {
@override
String get autoConnect => '自动连接';
@override
String get autoRun => '自动运行';
@override
String get autoUpdateHomeWidget => '自动更新桌面小部件';
@@ -652,10 +655,10 @@ class SZh extends S {
String get sftpRmrDirSummary => '在 SFTP 中使用 `rm -r` 来删除文件夹';
@override
String get sftpShowFoldersFirst => '排序时文件夹显示在前';
String get sftpSSHConnected => 'SFTP 已连接...';
@override
String get sftpSSHConnected => 'SFTP 已连接...';
String get sftpShowFoldersFirst => '排序时文件夹显示在前';
@override
String get showDistLogo => '显示发行版 Logo';
@@ -911,6 +914,9 @@ class SZhTw extends SZh {
@override
String get autoConnect => '自動連接';
@override
String get autoRun => '自動運行';
@override
String get autoUpdateHomeWidget => '自動更新桌面小部件';
@@ -1506,10 +1512,10 @@ class SZhTw extends SZh {
String get sftpRmrDirSummary => '在 SFTP 中使用 `rm -r` 來刪除文件夾';
@override
String get sftpShowFoldersFirst => '排序時文件夾顯示在前';
String get sftpSSHConnected => 'SFTP 已連接...';
@override
String get sftpSSHConnected => 'SFTP 已連接...';
String get sftpShowFoldersFirst => '排序時文件夾顯示在前';
@override
String get showDistLogo => '顯示發行版 Logo';

View File

@@ -48,7 +48,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.lollipopkit.flutter_server_box"
applicationId "tech.lolli.toolbox"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion

View File

@@ -1,5 +1,5 @@
PODS:
- countly_flutter (23.8.4):
- countly_flutter (23.12.1):
- Flutter
- file_picker (0.0.1):
- Flutter
@@ -76,19 +76,19 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/watch_connectivity/ios"
SPEC CHECKSUMS:
countly_flutter: d880b352f212d4f6453a87c85f0455f3b4b9c611
countly_flutter: 0b87be283b3ecef341b5f8d45ff97dd33ee966b9
file_picker: 880e54928ebe4aa405aaf4577f29a76a078341c6
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
icloud_storage: d9ac7a33ced81df08ba7ea1bf3099cc0ee58f60a
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
local_auth_ios: 5046a18c018dd973247a0564496c8898dbb5adf9
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
plain_notification_token: b36467dc91939a7b6754267c701bbaca14996ee1
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
watch_connectivity: 715eb484685e05846eab74795348a44bb2809b82
PODFILE CHECKSUM: ec6ef69056f066e8b21a3391082f23b5ad2d37f8

View File

@@ -318,7 +318,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1430;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -586,7 +586,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -596,7 +596,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -720,7 +720,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -730,7 +730,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -748,7 +748,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -758,7 +758,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -779,7 +779,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -792,7 +792,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -818,7 +818,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -831,7 +831,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -854,7 +854,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -867,7 +867,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -890,7 +890,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -902,7 +902,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -931,7 +931,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -943,7 +943,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;
@@ -969,7 +969,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -981,7 +981,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -53,34 +53,41 @@ extension DialogX on BuildContext {
Future<List<T>?> showPickDialog<T>({
required List<T?> items,
required String Function(T) name,
String Function(T)? name,
bool multi = true,
List<T>? initial,
bool clearable = false,
List<Widget>? actions,
}) async {
var vals = <T>[];
var vals = initial ?? <T>[];
final sure = await showRoundDialog<bool>(
title: Text(l10n.choose),
child: Choice<T>(
onChanged: (value) => vals = value,
multiple: multi,
clearable: true,
builder: (state, _) {
return Wrap(
children: List<Widget>.generate(
items.length,
(index) {
final item = items[index];
if (item == null) return UIs.placeholder;
return ChoiceChipX<T>(
label: name(item),
state: state,
value: item,
);
},
),
);
},
child: SingleChildScrollView(
child: Choice<T>(
onChanged: (value) => vals = value,
multiple: multi,
clearable: clearable,
value: vals,
builder: (state, _) {
return Wrap(
children: List<Widget>.generate(
items.length,
(index) {
final item = items[index];
if (item == null) return UIs.placeholder;
return ChoiceChipX<T>(
label: name?.call(item) ?? item.toString(),
state: state,
value: item,
);
},
),
);
},
),
),
actions: [
if (actions != null) ...actions,
TextButton(
onPressed: () => pop(true),
child: Text(l10n.ok),
@@ -95,12 +102,17 @@ extension DialogX on BuildContext {
Future<T?> showPickSingleDialog<T>({
required List<T?> items,
required String Function(T) name,
String Function(T)? name,
T? initial,
bool clearable = false,
List<Widget>? actions,
}) async {
final vals = await showPickDialog<T>(
items: items,
name: name,
multi: false,
initial: initial == null ? null : [initial],
actions: actions,
);
if (vals != null && vals.isNotEmpty) {
return vals.first;

View File

@@ -107,7 +107,7 @@ extension SSHClientX on SSHClient {
bool stdout = true,
bool stderr = true,
Map<String, String>? environment,
Future<void> Function(SSHSession)? action,
Future<void> Function(SSHSession)? action,
}) async {
final session = await execute(
command,

View File

@@ -80,4 +80,4 @@ Comparator.comparing<Type1, Type2>(Type1::getType2)
.thenCompare<Type4>(Type1::getType4)
.thenCompareReversed<Type5>(Type1::getType5)
*/
*/

View File

@@ -61,4 +61,4 @@ final isWeb = OS.type == OS.web;
final isMobile = OS.type == OS.ios || OS.type == OS.android;
final isDesktop =
OS.type == OS.linux || OS.type == OS.macos || OS.type == OS.windows;
const isDebuggingMobileLayoutOnDesktop = kDebugMode;
const isDebuggingMobileLayoutOnDesktop = kDebugMode;

View File

@@ -16,18 +16,24 @@ class Snippet implements TagPickable {
@HiveField(3)
final String? note;
/// List of server id that this snippet should be auto run on
@HiveField(4)
final List<String>? autoRunOn;
const Snippet({
required this.name,
required this.script,
this.tags,
this.note,
this.autoRunOn,
});
Snippet.fromJson(Map<String, dynamic> json)
: name = json['name'].toString(),
script = json['script'].toString(),
tags = json['tags']?.cast<String>(),
note = json['note']?.toString();
note = json['note']?.toString(),
autoRunOn = json['autoRunOn']?.cast<String>();
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
@@ -35,6 +41,7 @@ class Snippet implements TagPickable {
data['script'] = script;
data['tags'] = tags;
data['note'] = note;
data['autoRunOn'] = autoRunOn;
return data;
}

View File

@@ -21,13 +21,14 @@ class SnippetAdapter extends TypeAdapter<Snippet> {
script: fields[1] as String,
tags: (fields[2] as List?)?.cast<String>(),
note: fields[3] as String?,
autoRunOn: (fields[4] as List?)?.cast<String>(),
);
}
@override
void write(BinaryWriter writer, Snippet obj) {
writer
..writeByte(4)
..writeByte(5)
..writeByte(0)
..write(obj.name)
..writeByte(1)
@@ -35,7 +36,9 @@ class SnippetAdapter extends TypeAdapter<Snippet> {
..writeByte(2)
..write(obj.tags)
..writeByte(3)
..write(obj.note);
..write(obj.note)
..writeByte(4)
..write(obj.autoRunOn);
}
@override

View File

@@ -273,10 +273,9 @@ class ServerProvider extends ChangeNotifier {
ensure(await client.run(ShellFunc.installerMkdirs).string);
ensure(await client.runForOutput(ShellFunc.installerShellWriter,
action: (session) async {
session.stdin.add(ShellFunc.allScript.uint8List);
})
.string);
action: (session) async {
session.stdin.add(ShellFunc.allScript.uint8List);
}).string);
ensure(await client.run(ShellFunc.installerPermissionModifier).string);
}

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 746;
static const String engine = "3.16.9";
static const String buildAt = "2024-02-15 16:45:05";
static const int modifications = 2;
static const int script = 37;
static const int build = 761;
static const String engine = "3.19.0";
static const String buildAt = "2024-02-18 12:48:41";
static const int modifications = 10;
static const int script = 38;
}

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "Es kann nur eine automatische Sicherung gleichzeitig aktiviert werden.",
"autoCheckUpdate": "Aktualisierung automatisch prüfen",
"autoConnect": "Automatisch verbinden",
"autoRun": "Automatischer Start",
"autoUpdateHomeWidget": "Home-Widget automatisch aktualisieren",
"backup": "Backup",
"backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.",
@@ -207,8 +208,8 @@
"setting": "Einstellungen",
"sftpDlPrepare": "Verbindung vorbereiten...",
"sftpRmrDirSummary": "Verwenden Sie \"rm -r\", um das Verzeichnis in SFTP zu löschen.",
"sftpShowFoldersFirst": "Ordner zuerst anzeigen",
"sftpSSHConnected": "SFTP Verbunden",
"sftpShowFoldersFirst": "Ordner zuerst anzeigen",
"showDistLogo": "Distributionslogo anzeigen",
"shutdown": "Abschaltung",
"size": "Größe",

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "Only one automatic backup can be turned on at the same time.",
"autoCheckUpdate": "Auto check update",
"autoConnect": "Auto connect",
"autoRun": "Automatic Run",
"autoUpdateHomeWidget": "Auto update home widget",
"backup": "Backup",
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
@@ -207,8 +208,8 @@
"setting": "Settings",
"sftpDlPrepare": "Preparing to connect...",
"sftpRmrDirSummary": "Use `rm -r` to delete a folder in SFTP.",
"sftpShowFoldersFirst": "Disply folders first",
"sftpSSHConnected": "SFTP Connected",
"sftpShowFoldersFirst": "Disply folders first",
"showDistLogo": "Show distribution logo",
"shutdown": "Shutdown",
"size": "Size",

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "Une seule sauvegarde automatique peut être activée à la fois.",
"autoCheckUpdate": "Vérification automatique des mises à jour",
"autoConnect": "Connexion automatique",
"autoRun": "Exécution automatique",
"autoUpdateHomeWidget": "Mise à jour automatique du widget d'accueil",
"backup": "Sauvegarder",
"backupTip": "Les données exportées sont simplement chiffrées. \nVeuillez les conserver en lieu sûr.",
@@ -207,8 +208,8 @@
"setting": "Paramètres",
"sftpDlPrepare": "Préparation de la connexion...",
"sftpRmrDirSummary": "Utilisez `rm -r` pour supprimer un dossier dans SFTP.",
"sftpShowFoldersFirst": "Dossiers d'abord lors du tri",
"sftpSSHConnected": "SFTP connecté",
"sftpShowFoldersFirst": "Dossiers d'abord lors du tri",
"showDistLogo": "Afficher le logo de la distribution",
"shutdown": "Éteindre",
"size": "Taille",

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "Hanya satu pencadangan otomatis yang dapat diaktifkan pada saat yang bersamaan.",
"autoCheckUpdate": "Periksa pembaruan otomatis",
"autoConnect": "Hubungkan otomatis",
"autoRun": "Berjalan Otomatis",
"autoUpdateHomeWidget": "Widget Rumah Pembaruan Otomatis",
"backup": "Cadangan",
"backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.",
@@ -207,8 +208,8 @@
"setting": "Pengaturan",
"sftpDlPrepare": "Bersiap untuk terhubung ...",
"sftpRmrDirSummary": "Gunakan `rm -r` untuk menghapus dir di SFTP",
"sftpShowFoldersFirst": "Folder ditampilkan lebih dulu",
"sftpSSHConnected": "Sftp terhubung",
"sftpShowFoldersFirst": "Folder ditampilkan lebih dulu",
"showDistLogo": "Tampilkan logo distribusi",
"shutdown": "Matikan",
"size": "Ukuran",

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "只能同时开启一个自动备份",
"autoCheckUpdate": "自动检查更新",
"autoConnect": "自动连接",
"autoRun": "自动运行",
"autoUpdateHomeWidget": "自动更新桌面小部件",
"backup": "备份",
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
@@ -207,8 +208,8 @@
"setting": "设置",
"sftpDlPrepare": "准备连接至服务器...",
"sftpRmrDirSummary": "在 SFTP 中使用 `rm -r` 来删除文件夹",
"sftpShowFoldersFirst": "排序时文件夹显示在前",
"sftpSSHConnected": "SFTP 已连接...",
"sftpShowFoldersFirst": "排序时文件夹显示在前",
"showDistLogo": "显示发行版 Logo",
"shutdown": "关机",
"size": "大小",

View File

@@ -17,6 +17,7 @@
"autoBackupConflict": "只能同時開啓壹個自動備份",
"autoCheckUpdate": "自動檢查更新",
"autoConnect": "自動連接",
"autoRun": "自動運行",
"autoUpdateHomeWidget": "自動更新桌面小部件",
"backup": "備份",
"backupTip": "導出的數據僅進行了簡單加密,請妥善保管。",
@@ -207,8 +208,8 @@
"setting": "設置",
"sftpDlPrepare": "準備連接至服務器...",
"sftpRmrDirSummary": "在 SFTP 中使用 `rm -r` 來刪除文件夾",
"sftpShowFoldersFirst": "排序時文件夾顯示在前",
"sftpSSHConnected": "SFTP 已連接...",
"sftpShowFoldersFirst": "排序時文件夾顯示在前",
"showDistLogo": "顯示發行版 Logo",
"shutdown": "关机",
"size": "大小",

View File

@@ -855,7 +855,7 @@ class _SettingPageState extends State<SettingPage> {
children: [
_buildSftpRmrDir(),
_buildSftpOpenLastPath(),
_buildSftpShowFoldersFirst(),
_buildSftpShowFoldersFirst(),
].map((e) => CardX(child: e)).toList(),
);
}
@@ -870,7 +870,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSftpShowFoldersFirst() {
return ListTile(
title: Text(l10n.sftpShowFoldersFirst),
title: Text(l10n.sftpShowFoldersFirst),
trailing: StoreSwitch(prop: _setting.sftpShowFoldersFirst),
);
}

View File

@@ -30,8 +30,8 @@ class _SnippetEditPageState extends State<SnippetEditPage>
final _scriptController = TextEditingController();
final _noteController = TextEditingController();
final _scriptNode = FocusNode();
List<String> _tags = [];
final _autoRunOn = ValueNotifier(<String>[]);
final _tags = ValueNotifier(<String>[]);
@override
void dispose() {
@@ -98,8 +98,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
final snippet = Snippet(
name: name,
script: script,
tags: _tags.isEmpty ? null : _tags,
tags: _tags.value.isEmpty ? null : _tags.value,
note: note.isEmpty ? null : note,
autoRunOn: _autoRunOn.value.isEmpty ? null : _autoRunOn.value,
);
if (widget.snippet != null) {
Pros.snippet.update(widget.snippet!, snippet);
@@ -131,15 +132,20 @@ class _SnippetEditPageState extends State<SnippetEditPage>
label: l10n.note,
icon: Icons.note,
),
TagEditor(
tags: _tags,
onChanged: (p0) => setState(() {
_tags = p0;
}),
allTags: [...Pros.snippet.tags],
onRenameTag: (old, n) => setState(() {
Pros.snippet.renameTag(old, n);
}),
ValueListenableBuilder(
valueListenable: _tags,
builder: (_, vals, __) {
return TagEditor(
tags: _tags.value,
onChanged: (p0) => setState(() {
_tags.value = p0;
}),
allTags: [...Pros.snippet.tags],
onRenameTag: (old, n) => setState(() {
Pros.snippet.renameTag(old, n);
}),
);
},
),
Input(
controller: _scriptController,
@@ -150,11 +156,41 @@ class _SnippetEditPageState extends State<SnippetEditPage>
label: l10n.snippet,
icon: Icons.code,
),
_buildAutoRunOn(),
_buildTip(),
],
);
}
Widget _buildAutoRunOn() {
return CardX(
child: ValueListenableBuilder(
valueListenable: _autoRunOn,
builder: (_, vals, __) {
return ListTile(
title: Text(l10n.autoRun),
trailing: const Icon(Icons.keyboard_arrow_right),
subtitle: vals.isEmpty
? null
: Text(
vals.join(', '),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
onTap: () async {
final serverIds = await context.showPickDialog(
items: Pros.server.serverOrder,
initial: vals,
);
if (serverIds != null) {
_autoRunOn.value = serverIds;
}
},
);
},
));
}
Widget _buildTip() {
return CardX(
child: MarkdownBody(
@@ -174,16 +210,20 @@ ${Snippet.fmtArgs.keys.map((e) => '`$e`').join(', ')}
@override
void afterFirstLayout(BuildContext context) {
if (widget.snippet != null) {
_nameController.text = widget.snippet!.name;
_scriptController.text = widget.snippet!.script;
if (widget.snippet!.note != null) {
_noteController.text = widget.snippet!.note!;
final snippet = widget.snippet;
if (snippet != null) {
_nameController.text = snippet.name;
_scriptController.text = snippet.script;
if (snippet.note != null) {
_noteController.text = snippet.note!;
}
if (widget.snippet!.tags != null) {
_tags = widget.snippet!.tags!;
setState(() {});
if (snippet.tags != null) {
_tags.value = snippet.tags!;
}
if (snippet.autoRunOn != null) {
_autoRunOn.value = snippet.autoRunOn!;
}
}
}

View File

@@ -382,6 +382,13 @@ class _SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin {
if (widget.initCmd != null) {
_terminal.textInput(widget.initCmd!);
_terminal.keyInput(TerminalKey.enter);
} else {
for (final snippet in Pros.snippet.snippets) {
if (snippet.autoRunOn?.contains(widget.spi.id) == true) {
_terminal.textInput(snippet.script);
_terminal.keyInput(TerminalKey.enter);
}
}
}
await session.done;

View File

@@ -59,7 +59,8 @@ class _TagEditorState extends State<TagEditor> {
Widget build(BuildContext context) {
return CardX(
child: ListTile(
leading: const Icon(Icons.tag),
// Align the place of TextField.prefixIcon
leading: const Icon(Icons.tag).padding(const EdgeInsets.only(left: 6)),
title: _buildTags(widget.tags),
trailing: const Icon(Icons.add).tap(
onTap: () {

View File

@@ -54,10 +54,10 @@ SPEC CHECKSUMS:
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
icloud_storage: 33b05299e26d1391d724da8d62860e702380a1cd
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8

View File

@@ -220,7 +220,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
33CC10EC2044A3C60003C045 = {
@@ -439,7 +439,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -449,7 +449,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -574,7 +574,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -584,7 +584,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -604,7 +604,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 746;
CURRENT_PROJECT_VERSION = 761;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
@@ -615,7 +615,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.746;
MARKETING_VERSION = 1.0.761;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"