diff --git a/.vscode/cli.code-snippets b/.vscode/cli.code-snippets index 4772a0f..e96cf45 100644 --- a/.vscode/cli.code-snippets +++ b/.vscode/cli.code-snippets @@ -20,7 +20,7 @@ "import \"package:discloud/cli/disposable.dart\";", "import \"package:discloud/extensions/command.dart\";", "", - "class ${1:${TM_FILENAME_BASE/(^\\w+)/${1:/pascalcase}/}}Command extends Command with Disposable {", + "final class ${1:${TM_FILENAME_BASE/(^\\w+)/${1:/pascalcase}/}}Command extends Command with Disposable {", "\t${1:${TM_FILENAME_BASE/(^\\w+)/${1:/pascalcase}/}}Command() {$4}", "", "\t@override", diff --git a/docs/commands.md b/docs/commands.md index c2a6801..76e5371 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -561,8 +561,9 @@ Usage: discloud user info [arguments] Set your locale Usage: discloud user locale [arguments] --h, --help Print this usage information. --l, --locale= (mandatory) +-h, --help Print this usage information. +-l, --locale= +-s, --system Use current system language (C.UTF-8) ``` ### zip diff --git a/lib/cli/context.dart b/lib/cli/context.dart index 56e4ec3..1d1b068 100644 --- a/lib/cli/context.dart +++ b/lib/cli/context.dart @@ -38,8 +38,8 @@ class CliContext implements Disposable { required this.printer, required this.store, required this.subscriptions, - required Stopwatch stopwatch, - }) : _stopwatch = stopwatch; + required this._stopwatch, + }); final List subscriptions; @@ -64,6 +64,8 @@ class CliContext implements Disposable { final LocalStore store; final IPrinter printer; + String get locale => Platform.localeName; + Directory get workspaceFolder => _workspaceFolder; String get rootFilePath => _rootFilePath; diff --git a/lib/cli/printer/console_printer.dart b/lib/cli/printer/console_printer.dart index 2efa92b..06fc848 100644 --- a/lib/cli/printer/console_printer.dart +++ b/lib/cli/printer/console_printer.dart @@ -36,37 +36,25 @@ class ConsolePrinter implements IPrinter { @override void error(Object? object) { - if (_spin case final spin?) { - spin.fail(object.toString()); - return; - } + if (_spin case final spin?) return spin.fail(object.toString()); stderr.writeln(object); } @override void info(Object? object) { - if (_spin case final spin?) { - spin.info(object.toString()); - return; - } + if (_spin case final spin?) return spin.info(object.toString()); writeln(object); } @override void success(Object? object) { - if (_spin case final spin?) { - spin.success(object.toString()); - return; - } + if (_spin case final spin?) return spin.success(object.toString()); writeln(object); } @override void warn(Object? object) { - if (_spin case final spin?) { - spin.warn(object.toString()); - return; - } + if (_spin case final spin?) return spin.warn(object.toString()); writeln(object); } diff --git a/lib/cli/runner.dart b/lib/cli/runner.dart index b8d8b20..4ca2a79 100644 --- a/lib/cli/runner.dart +++ b/lib/cli/runner.dart @@ -33,6 +33,7 @@ class CliCommandRunner extends CommandRunner { addCommand(InitCommand()); addCommand(LoginCommand()); addCommand(SubdomainCommand()); + addCommand(SystemCommand()); addCommand(TeamCommand()); addCommand(UserCommand()); addCommand(WaitCommand()); diff --git a/lib/cli/spin/cli_spin.dart b/lib/cli/spin/cli_spin.dart index d985b1f..e2b9ded 100644 --- a/lib/cli/spin/cli_spin.dart +++ b/lib/cli/spin/cli_spin.dart @@ -8,13 +8,11 @@ import "package:tint/tint.dart"; part "timer_cli_spin.dart"; -const _defaultTimerInterval = 100; - void _noop() {} class CLISpin implements ISpin { factory CLISpin({String? text, bool showDuration = false}) => - showDuration ? _TimerCliSpin._(text: text) : ._(.new(text: text)); + showDuration ? _TimerCLISpin._(text: text) : ._(.new(text: text)); const CLISpin._(this._spin); diff --git a/lib/cli/spin/timer_cli_spin.dart b/lib/cli/spin/timer_cli_spin.dart index 32a9bd5..0226dbc 100644 --- a/lib/cli/spin/timer_cli_spin.dart +++ b/lib/cli/spin/timer_cli_spin.dart @@ -1,24 +1,22 @@ part of "cli_spin.dart"; -class _TimerCliSpin extends CLISpin { +class _TimerCLISpin extends CLISpin { static String? _resolveSuffixText(Stopwatch stopwatch) { if (stopwatch.isRunning) return stopwatch.elapsed.pretty().dim(); return null; } - _TimerCliSpin._({String? text}) + _TimerCLISpin._({String? text}) : _stopwatch = .new()..start(), _timer = .new(.zero, _noop), super._(.new(text: text)) { - _interval = _spin.spinner?.interval ?? _defaultTimerInterval; - _timerInterval = .new(milliseconds: _interval); + _timerDuration = .new(milliseconds: _spin.interval); } final Stopwatch _stopwatch; Timer _timer; - late final int _interval; - late final Duration _timerInterval; + late final Duration _timerDuration; void _setSuffixTextAndStopTimers() { _timer.cancel(); @@ -40,14 +38,13 @@ class _TimerCliSpin extends CLISpin { void info([String? text]) { _setSuffixTextAndStopTimers(); super.info(text); - _stopwatch.stop(); } @override void start([String? text]) { _stopwatch.resetAndStart(); _timer.cancel(); - _timer = .periodic(_timerInterval, _timerCallback); + _timer = .periodic(_timerDuration, _timerCallback); super.start(text); } @@ -69,13 +66,11 @@ class _TimerCliSpin extends CLISpin { void success([String? text]) { _setSuffixTextAndStopTimers(); super.success(text); - _stopwatch.stop(); } @override void warn([String? text]) { _setSuffixTextAndStopTimers(); super.warn(text); - _stopwatch.stop(); } } diff --git a/lib/commands/app.dart b/lib/commands/app.dart index 16073a7..0b67813 100644 --- a/lib/commands/app.dart +++ b/lib/commands/app.dart @@ -15,7 +15,7 @@ import "package:discloud/commands/app/status.dart"; import "package:discloud/commands/app/stop.dart"; import "package:discloud/commands/app/upload.dart"; -class AppCommand extends Command { +final class AppCommand extends Command { AppCommand() { addSubcommand(AppAptCommand()); addSubcommand(AppBackupCommand()); diff --git a/lib/commands/app/apt.dart b/lib/commands/app/apt.dart index bd90cd2..dec0e4f 100644 --- a/lib/commands/app/apt.dart +++ b/lib/commands/app/apt.dart @@ -2,7 +2,7 @@ import "package:args/command_runner.dart"; import "package:discloud/commands/app/apt/install.dart"; import "package:discloud/commands/app/apt/uninstall.dart"; -class AppAptCommand extends Command { +final class AppAptCommand extends Command { AppAptCommand() { addSubcommand(AppAptInstallCommand()); addSubcommand(AppAptUninstallCommand()); diff --git a/lib/commands/app/apt/install.dart b/lib/commands/app/apt/install.dart index bfb3774..6a5f7d0 100644 --- a/lib/commands/app/apt/install.dart +++ b/lib/commands/app/apt/install.dart @@ -5,7 +5,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/services/discloud/constants.dart"; import "package:discloud/utils/messages.dart"; -class AppAptInstallCommand extends Command { +final class AppAptInstallCommand extends Command { AppAptInstallCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/apt/uninstall.dart b/lib/commands/app/apt/uninstall.dart index 99fe592..85f3fbe 100644 --- a/lib/commands/app/apt/uninstall.dart +++ b/lib/commands/app/apt/uninstall.dart @@ -5,7 +5,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/services/discloud/constants.dart"; import "package:discloud/utils/messages.dart"; -class AppAptUninstallCommand extends Command { +final class AppAptUninstallCommand extends Command { AppAptUninstallCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/backup.dart b/lib/commands/app/backup.dart index 7e2348c..9558200 100644 --- a/lib/commands/app/backup.dart +++ b/lib/commands/app/backup.dart @@ -13,7 +13,7 @@ import "package:discloud/utils/speed_monitor.dart"; const _pSep = "/"; -class AppBackupCommand extends Command with Disposable { +final class AppBackupCommand extends Command with Disposable { AppBackupCommand() { argParser ..addOption("app", mandatory: true, valueHelp: "all") diff --git a/lib/commands/app/commit.dart b/lib/commands/app/commit.dart index 82877b0..c947110 100644 --- a/lib/commands/app/commit.dart +++ b/lib/commands/app/commit.dart @@ -13,7 +13,7 @@ import "package:discloud/utils/zip.dart"; import "package:discloud_config/discloud_config.dart"; import "package:path/path.dart" hide context; -class AppCommitCommand extends Command with Disposable { +final class AppCommitCommand extends Command with Disposable { AppCommitCommand() { argParser ..addOption( @@ -82,6 +82,7 @@ class AppCommitCommand extends Command with Disposable { ); }, onUploadDone: () { + _file = null; spinner.start("Processing..."); }, ); diff --git a/lib/commands/app/console.dart b/lib/commands/app/console.dart index 559f9c7..0d9058e 100644 --- a/lib/commands/app/console.dart +++ b/lib/commands/app/console.dart @@ -8,7 +8,7 @@ import "package:discloud/services/discloud/exception.dart"; import "package:discloud/utils/messages.dart"; import "package:tint/tint.dart"; -class AppConsoleCommand extends Command { +final class AppConsoleCommand extends Command { AppConsoleCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/delete.dart b/lib/commands/app/delete.dart index 48c0fa0..bc86e52 100644 --- a/lib/commands/app/delete.dart +++ b/lib/commands/app/delete.dart @@ -5,7 +5,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; import "package:interact/interact.dart"; -class AppDeleteCommand extends Command { +final class AppDeleteCommand extends Command { AppDeleteCommand() { argParser ..addFlag( diff --git a/lib/commands/app/info.dart b/lib/commands/app/info.dart index baafed4..787fd8d 100644 --- a/lib/commands/app/info.dart +++ b/lib/commands/app/info.dart @@ -20,7 +20,7 @@ const _keysIgnore = { "type", }; -class AppInfoCommand extends Command { +final class AppInfoCommand extends Command { AppInfoCommand() { argParser.addOption("app", defaultsTo: "all"); } diff --git a/lib/commands/app/logs.dart b/lib/commands/app/logs.dart index 19c7d0a..1882cab 100644 --- a/lib/commands/app/logs.dart +++ b/lib/commands/app/logs.dart @@ -8,7 +8,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; import "package:path/path.dart" hide context; -class AppLogsCommand extends Command { +final class AppLogsCommand extends Command { AppLogsCommand() { argParser ..addOption( diff --git a/lib/commands/app/mod.dart b/lib/commands/app/mod.dart index 6638494..580827a 100644 --- a/lib/commands/app/mod.dart +++ b/lib/commands/app/mod.dart @@ -4,7 +4,7 @@ import "package:discloud/commands/app/mod/delete.dart"; import "package:discloud/commands/app/mod/edit.dart"; import "package:discloud/commands/app/mod/info.dart"; -class AppModCommand extends Command { +final class AppModCommand extends Command { AppModCommand() { addSubcommand(AppModAddCommand()); addSubcommand(AppModDeleteCommand()); diff --git a/lib/commands/app/mod/add.dart b/lib/commands/app/mod/add.dart index 96def43..80be8e0 100644 --- a/lib/commands/app/mod/add.dart +++ b/lib/commands/app/mod/add.dart @@ -5,7 +5,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/services/discloud/constants.dart"; import "package:discloud/utils/messages.dart"; -class AppModAddCommand extends Command { +final class AppModAddCommand extends Command { AppModAddCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/mod/delete.dart b/lib/commands/app/mod/delete.dart index 0b81075..34b59c5 100644 --- a/lib/commands/app/mod/delete.dart +++ b/lib/commands/app/mod/delete.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class AppModDeleteCommand extends Command { +final class AppModDeleteCommand extends Command { AppModDeleteCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/mod/edit.dart b/lib/commands/app/mod/edit.dart index 3b8fce4..f8eeded 100644 --- a/lib/commands/app/mod/edit.dart +++ b/lib/commands/app/mod/edit.dart @@ -5,7 +5,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/services/discloud/constants.dart"; import "package:discloud/utils/messages.dart"; -class AppModEditCommand extends Command { +final class AppModEditCommand extends Command { AppModEditCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/mod/info.dart b/lib/commands/app/mod/info.dart index 32c3d1f..f8909b3 100644 --- a/lib/commands/app/mod/info.dart +++ b/lib/commands/app/mod/info.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class AppModInfoCommand extends Command { +final class AppModInfoCommand extends Command { AppModInfoCommand() { argParser.addOption("app", mandatory: true); } diff --git a/lib/commands/app/profile.dart b/lib/commands/app/profile.dart index c8f16a4..81dbc03 100644 --- a/lib/commands/app/profile.dart +++ b/lib/commands/app/profile.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class AppProfileCommand extends Command { +final class AppProfileCommand extends Command { AppProfileCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/ram.dart b/lib/commands/app/ram.dart index af163ae..03aa634 100644 --- a/lib/commands/app/ram.dart +++ b/lib/commands/app/ram.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; import "package:discloud_config/discloud_config.dart"; -class AppRamCommand extends Command { +final class AppRamCommand extends Command { AppRamCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/app/restart.dart b/lib/commands/app/restart.dart index 6cd60d2..7971977 100644 --- a/lib/commands/app/restart.dart +++ b/lib/commands/app/restart.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class AppRestartCommand extends Command { +final class AppRestartCommand extends Command { AppRestartCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/app/start.dart b/lib/commands/app/start.dart index 864b3bc..8e78a21 100644 --- a/lib/commands/app/start.dart +++ b/lib/commands/app/start.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class AppStartCommand extends Command { +final class AppStartCommand extends Command { AppStartCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/app/status.dart b/lib/commands/app/status.dart index 9cba526..7f52666 100644 --- a/lib/commands/app/status.dart +++ b/lib/commands/app/status.dart @@ -8,7 +8,7 @@ import "package:discloud/utils/messages.dart"; const _keysToIgnore = {"netIO"}; -class AppStatusCommand extends Command { +final class AppStatusCommand extends Command { AppStatusCommand() { argParser.addOption("app", mandatory: true); } diff --git a/lib/commands/app/stop.dart b/lib/commands/app/stop.dart index ef4daaa..d3d8d53 100644 --- a/lib/commands/app/stop.dart +++ b/lib/commands/app/stop.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class AppStopCommand extends Command { +final class AppStopCommand extends Command { AppStopCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/app/upload.dart b/lib/commands/app/upload.dart index dc00935..c2eba3d 100644 --- a/lib/commands/app/upload.dart +++ b/lib/commands/app/upload.dart @@ -12,7 +12,7 @@ import "package:discloud/utils/zip.dart"; import "package:discloud_config/discloud_config.dart"; import "package:path/path.dart" hide context; -class AppUploadCommand extends Command with Disposable { +final class AppUploadCommand extends Command with Disposable { AppUploadCommand() { argParser.addMultiOption("glob", abbr: "g", defaultsTo: const ["**"]); } @@ -77,6 +77,7 @@ class AppUploadCommand extends Command with Disposable { ); }, onUploadDone: () { + _file = null; spinner.start("Processing..."); }, ); diff --git a/lib/commands/commands.dart b/lib/commands/commands.dart index 44c2c52..a1f50ce 100644 --- a/lib/commands/commands.dart +++ b/lib/commands/commands.dart @@ -3,5 +3,6 @@ export "domain.dart"; export "init.dart"; export "login.dart"; export "subdomain.dart"; +export "system.dart"; export "user.dart"; export "zip.dart"; diff --git a/lib/commands/domain.dart b/lib/commands/domain.dart index b011c00..77d25e3 100644 --- a/lib/commands/domain.dart +++ b/lib/commands/domain.dart @@ -5,7 +5,7 @@ import "package:discloud/commands/domain/edit.dart"; import "package:discloud/commands/domain/info.dart"; import "package:discloud/commands/domain/verify.dart"; -class DomainCommand extends Command { +final class DomainCommand extends Command { DomainCommand() { addSubcommand(CustomdomainCreateCommand()); addSubcommand(CustomdomainDeleteCommand()); diff --git a/lib/commands/domain/create.dart b/lib/commands/domain/create.dart index 757b721..3fafc3f 100644 --- a/lib/commands/domain/create.dart +++ b/lib/commands/domain/create.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class CustomdomainCreateCommand extends Command { +final class CustomdomainCreateCommand extends Command { CustomdomainCreateCommand() { argParser ..addOption("id", aliases: const ["domain"], mandatory: true) diff --git a/lib/commands/domain/delete.dart b/lib/commands/domain/delete.dart index a324dd6..bbf0749 100644 --- a/lib/commands/domain/delete.dart +++ b/lib/commands/domain/delete.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class CustomdomainDeleteCommand extends Command { +final class CustomdomainDeleteCommand extends Command { CustomdomainDeleteCommand() { argParser.addOption("id", aliases: const ["domain"], mandatory: true); } diff --git a/lib/commands/domain/edit.dart b/lib/commands/domain/edit.dart index cc5be11..9ce2d97 100644 --- a/lib/commands/domain/edit.dart +++ b/lib/commands/domain/edit.dart @@ -5,7 +5,7 @@ import "package:discloud/cli/disposable.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class CustomdomainEditCommand extends Command with Disposable { +final class CustomdomainEditCommand extends Command with Disposable { CustomdomainEditCommand() { argParser ..addOption("id", aliases: const ["domain"], mandatory: true) diff --git a/lib/commands/domain/info.dart b/lib/commands/domain/info.dart index 1f6edc8..665df61 100644 --- a/lib/commands/domain/info.dart +++ b/lib/commands/domain/info.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class CustomdomainInfoCommand extends Command { +final class CustomdomainInfoCommand extends Command { CustomdomainInfoCommand() { argParser.addOption("id", aliases: const ["domain"], defaultsTo: "all"); } diff --git a/lib/commands/domain/verify.dart b/lib/commands/domain/verify.dart index 7043319..07027ac 100644 --- a/lib/commands/domain/verify.dart +++ b/lib/commands/domain/verify.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class CustomdomainVerifyCommand extends Command { +final class CustomdomainVerifyCommand extends Command { CustomdomainVerifyCommand() { argParser.addOption("id", aliases: const ["domain"], mandatory: true); } diff --git a/lib/commands/init.dart b/lib/commands/init.dart index 2d42cd7..b1e76d2 100644 --- a/lib/commands/init.dart +++ b/lib/commands/init.dart @@ -7,7 +7,7 @@ import "package:discloud/extensions/string.dart"; import "package:discloud/services/discloud/constants.dart"; import "package:discloud_config/discloud_config.dart"; -class InitCommand extends Command { +final class InitCommand extends Command { InitCommand() { argParser ..addFlag( @@ -53,7 +53,7 @@ class InitCommand extends Command { throw Exception("${DiscloudConfig.filename} already exists!"); } - final buffer = StringBuffer() + final StringBuffer buffer = .new() ..writeAll([ "# https://docs.discloud.com/en/discloud.config", if (args.apt case final v when v.isNotEmpty) "APT=${v.join(",")}", diff --git a/lib/commands/login.dart b/lib/commands/login.dart index 3b6a0c5..166b080 100644 --- a/lib/commands/login.dart +++ b/lib/commands/login.dart @@ -4,7 +4,7 @@ import "package:discloud/services/discloud/utils.dart"; import "package:discloud/utils/messages.dart"; import "package:interact/interact.dart"; -class LoginCommand extends Command { +final class LoginCommand extends Command { @override final name = "login"; diff --git a/lib/commands/subdomain.dart b/lib/commands/subdomain.dart index 8710f57..1340c67 100644 --- a/lib/commands/subdomain.dart +++ b/lib/commands/subdomain.dart @@ -3,7 +3,7 @@ import "package:discloud/commands/subdomain/create.dart"; import "package:discloud/commands/subdomain/delete.dart"; import "package:discloud/commands/subdomain/info.dart"; -class SubdomainCommand extends Command { +final class SubdomainCommand extends Command { SubdomainCommand() { addSubcommand(SubdomainCreateCommand()); addSubcommand(SubdomainDeleteCommand()); diff --git a/lib/commands/subdomain/create.dart b/lib/commands/subdomain/create.dart index 6fa1e35..ca30588 100644 --- a/lib/commands/subdomain/create.dart +++ b/lib/commands/subdomain/create.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class SubdomainCreateCommand extends Command { +final class SubdomainCreateCommand extends Command { SubdomainCreateCommand() { argParser.addOption("id", aliases: const ["subdomain"], mandatory: true); } diff --git a/lib/commands/subdomain/delete.dart b/lib/commands/subdomain/delete.dart index 563fad4..39dfec9 100644 --- a/lib/commands/subdomain/delete.dart +++ b/lib/commands/subdomain/delete.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class SubdomainDeleteCommand extends Command { +final class SubdomainDeleteCommand extends Command { SubdomainDeleteCommand() { argParser.addOption("id", aliases: const ["subdomain"], mandatory: true); } diff --git a/lib/commands/subdomain/info.dart b/lib/commands/subdomain/info.dart index 58d92cb..0c3abb6 100644 --- a/lib/commands/subdomain/info.dart +++ b/lib/commands/subdomain/info.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/ascii_table.dart"; import "package:discloud/utils/messages.dart"; -class SubdomainInfoCommand extends Command { +final class SubdomainInfoCommand extends Command { SubdomainInfoCommand() { argParser.addOption("id", aliases: const ["subdomain"], defaultsTo: "all"); } diff --git a/lib/commands/system.dart b/lib/commands/system.dart new file mode 100644 index 0000000..8b91153 --- /dev/null +++ b/lib/commands/system.dart @@ -0,0 +1,17 @@ +import "package:args/command_runner.dart"; +import "package:discloud/commands/system/locale.dart"; + +final class SystemCommand extends Command { + SystemCommand() { + addSubcommand(SystemLocaleCommand()); + } + + @override + final name = "system"; + + @override + final description = "View system info"; + + @override + final hidden = true; +} diff --git a/lib/commands/system/locale.dart b/lib/commands/system/locale.dart new file mode 100644 index 0000000..9dc3e4b --- /dev/null +++ b/lib/commands/system/locale.dart @@ -0,0 +1,31 @@ +import "dart:async"; +import "dart:io"; + +import "package:args/command_runner.dart"; +import "package:discloud/extensions/command.dart"; +import "package:intl/intl.dart"; + +final class SystemLocaleCommand extends Command { + SystemLocaleCommand(); + + @override + final name = "locale"; + + @override + final description = "Get locale info"; + + @override + Future run() async { + final StringBuffer sb = .new() + ..writeAll([ + "Platform locale: ${Platform.localeName}", + "Current locale: ${Intl.getCurrentLocale()}", + "Default locale: ${Intl.defaultLocale}", + "System locale: ${Intl.systemLocale}", + "Canonicalized locale: ${Intl.canonicalizedLocale(Platform.localeName)}", + "Short locale: ${Intl.shortLocale(Platform.localeName)}", + ], "\n"); + + context.printer.info(sb); + } +} diff --git a/lib/commands/team.dart b/lib/commands/team.dart index 80150f9..f3cbd5a 100644 --- a/lib/commands/team.dart +++ b/lib/commands/team.dart @@ -9,7 +9,7 @@ import "package:discloud/commands/team/start.dart"; import "package:discloud/commands/team/status.dart"; import "package:discloud/commands/team/stop.dart"; -class TeamCommand extends Command { +final class TeamCommand extends Command { TeamCommand() { addSubcommand(TeamBackupCommand()); addSubcommand(TeamCommitCommand()); diff --git a/lib/commands/team/backup.dart b/lib/commands/team/backup.dart index 20f6e26..8e68fc2 100644 --- a/lib/commands/team/backup.dart +++ b/lib/commands/team/backup.dart @@ -13,7 +13,7 @@ import "package:discloud/utils/speed_monitor.dart"; const _pSep = "/"; -class TeamBackupCommand extends Command with Disposable { +final class TeamBackupCommand extends Command with Disposable { TeamBackupCommand() { argParser ..addOption("app", mandatory: true, valueHelp: "all") diff --git a/lib/commands/team/commit.dart b/lib/commands/team/commit.dart index baabbd3..2cb1986 100644 --- a/lib/commands/team/commit.dart +++ b/lib/commands/team/commit.dart @@ -13,7 +13,7 @@ import "package:discloud/utils/zip.dart"; import "package:discloud_config/discloud_config.dart"; import "package:path/path.dart" hide context; -class TeamCommitCommand extends Command with Disposable { +final class TeamCommitCommand extends Command with Disposable { TeamCommitCommand() { argParser ..addOption( @@ -82,6 +82,7 @@ class TeamCommitCommand extends Command with Disposable { ); }, onUploadDone: () { + _file = null; spinner.start("Processing..."); }, ); diff --git a/lib/commands/team/info.dart b/lib/commands/team/info.dart index fbe5219..0484575 100644 --- a/lib/commands/team/info.dart +++ b/lib/commands/team/info.dart @@ -19,7 +19,7 @@ const _keysIgnore = { "type", }; -class TeamInfoCommand extends Command { +final class TeamInfoCommand extends Command { TeamInfoCommand() { argParser.addOption("app"); } diff --git a/lib/commands/team/logs.dart b/lib/commands/team/logs.dart index 30d4c8c..c0e0125 100644 --- a/lib/commands/team/logs.dart +++ b/lib/commands/team/logs.dart @@ -8,7 +8,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; import "package:path/path.dart" hide context; -class TeamLogsCommand extends Command { +final class TeamLogsCommand extends Command { TeamLogsCommand() { argParser ..addOption( diff --git a/lib/commands/team/ram.dart b/lib/commands/team/ram.dart index 3731d45..c4222f4 100644 --- a/lib/commands/team/ram.dart +++ b/lib/commands/team/ram.dart @@ -6,7 +6,7 @@ import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; import "package:discloud_config/discloud_config.dart"; -class TeamRamCommand extends Command { +final class TeamRamCommand extends Command { TeamRamCommand() { argParser ..addOption("app", mandatory: true) diff --git a/lib/commands/team/restart.dart b/lib/commands/team/restart.dart index 8c91b81..c0038b8 100644 --- a/lib/commands/team/restart.dart +++ b/lib/commands/team/restart.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class TeamRestartCommand extends Command { +final class TeamRestartCommand extends Command { TeamRestartCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/team/start.dart b/lib/commands/team/start.dart index a1f2d92..c7b6655 100644 --- a/lib/commands/team/start.dart +++ b/lib/commands/team/start.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class TeamStartCommand extends Command { +final class TeamStartCommand extends Command { TeamStartCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/team/status.dart b/lib/commands/team/status.dart index 97657ac..b9b7430 100644 --- a/lib/commands/team/status.dart +++ b/lib/commands/team/status.dart @@ -8,7 +8,7 @@ import "package:discloud/utils/messages.dart"; const _keysToIgnore = {"netIO"}; -class TeamStatusCommand extends Command { +final class TeamStatusCommand extends Command { TeamStatusCommand() { argParser.addOption("app", mandatory: true); } diff --git a/lib/commands/team/stop.dart b/lib/commands/team/stop.dart index 0c48665..3e3e523 100644 --- a/lib/commands/team/stop.dart +++ b/lib/commands/team/stop.dart @@ -4,7 +4,7 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class TeamStopCommand extends Command { +final class TeamStopCommand extends Command { TeamStopCommand() { argParser.addOption("app", valueHelp: "all"); } diff --git a/lib/commands/user.dart b/lib/commands/user.dart index b32e982..58c17e3 100644 --- a/lib/commands/user.dart +++ b/lib/commands/user.dart @@ -2,7 +2,7 @@ import "package:args/command_runner.dart"; import "package:discloud/commands/user/info.dart"; import "package:discloud/commands/user/locale.dart"; -class UserCommand extends Command { +final class UserCommand extends Command { UserCommand() { addSubcommand(UserInfoCommand()); addSubcommand(UserLocaleCommand()); diff --git a/lib/commands/user/info.dart b/lib/commands/user/info.dart index 1f9ed02..2144b90 100644 --- a/lib/commands/user/info.dart +++ b/lib/commands/user/info.dart @@ -8,7 +8,7 @@ import "package:discloud/utils/messages.dart"; const _keysIgnore = {"avatar"}; -class UserInfoCommand extends Command { +final class UserInfoCommand extends Command { @override final name = "info"; diff --git a/lib/commands/user/locale.dart b/lib/commands/user/locale.dart index 32ece00..6f8fcd9 100644 --- a/lib/commands/user/locale.dart +++ b/lib/commands/user/locale.dart @@ -4,19 +4,21 @@ import "package:args/command_runner.dart"; import "package:discloud/extensions/command.dart"; import "package:discloud/utils/messages.dart"; -class UserLocaleCommand extends Command { +final class UserLocaleCommand extends Command { static const _localePattern = r"^\w{2}[-_]\w{2}$"; static final _localeRegexp = RegExp(_localePattern); static final _localeName = _localeRegexp.firstMatch(Platform.localeName)?.input ?? "en-US"; UserLocaleCommand() { - argParser.addOption( - "locale", - abbr: "l", - mandatory: true, - valueHelp: _localeName, - ); + argParser + ..addOption("locale", abbr: "l", valueHelp: _localeName) + ..addFlag( + "system", + abbr: "s", + help: "Use current system language (${Platform.localeName})", + negatable: false, + ); } @override @@ -27,7 +29,9 @@ class UserLocaleCommand extends Command { @override Future run() async { - final locale = argResults!.option("locale"); + final system = argResults!.flag("system"); + + final locale = system ? Platform.localeName : argResults!.option("locale"); final spinner = context.printer.spin(text: "Defining locale..."); diff --git a/lib/commands/wait.dart b/lib/commands/wait.dart index 7e30a0f..dac6c4e 100644 --- a/lib/commands/wait.dart +++ b/lib/commands/wait.dart @@ -2,9 +2,10 @@ import "dart:async"; import "package:args/command_runner.dart"; import "package:discloud/cli/disposable.dart"; +import "package:discloud/extensions/command.dart"; import "package:discloud/extensions/num.dart"; -class WaitCommand extends Command with Disposable { +final class WaitCommand extends Command with Disposable { WaitCommand(); @override @@ -31,6 +32,6 @@ class WaitCommand extends Command with Disposable { @override FutureOr dispose() { // ignore: no_runtimetype_tostring - print("$hashCode $runtimeType disposed"); + context.printer.info("$hashCode $runtimeType disposed"); } } diff --git a/lib/commands/zip.dart b/lib/commands/zip.dart index 6f08bcc..2fe6c9e 100644 --- a/lib/commands/zip.dart +++ b/lib/commands/zip.dart @@ -10,7 +10,7 @@ import "package:discloud/utils/bytes.dart"; import "package:discloud/utils/zip.dart"; import "package:path/path.dart" hide context; -class ZipCommand extends Command with Disposable { +final class ZipCommand extends Command with Disposable { ZipCommand() { argParser ..addOption("encoding", abbr: "e", allowed: const ["buffer"], hide: true) diff --git a/lib/extensions/duration.dart b/lib/extensions/duration.dart index 506f1e7..a4c9f6f 100644 --- a/lib/extensions/duration.dart +++ b/lib/extensions/duration.dart @@ -1,12 +1,20 @@ +import "dart:io"; + import "package:duration/duration.dart"; import "package:duration/locale.dart"; +import "package:intl/intl.dart"; extension DurationExtension on Duration { + static final DurationLocale _durationLocale = + .fromLanguageCode(Platform.localeName) ?? + .fromLanguageCode(Intl.shortLocale(Platform.localeName)) ?? + const EnglishDurationLocale(); + String pretty({ bool abbreviated = true, String? conjunction, String? delimiter = " ", - DurationLocale locale = const EnglishDurationLocale(), + DurationLocale? locale, int maxUnits = 0, String? spacer = "", DurationTersity tersity = .millisecond, @@ -16,7 +24,7 @@ extension DurationExtension on Duration { abbreviated: abbreviated, conjunction: conjunction, delimiter: delimiter, - locale: locale, + locale: locale ?? _durationLocale, maxUnits: maxUnits, spacer: spacer, tersity: tersity, diff --git a/lib/extensions/io_http_client.dart b/lib/extensions/io_http_client.dart index 02fd755..9bffbdc 100644 --- a/lib/extensions/io_http_client.dart +++ b/lib/extensions/io_http_client.dart @@ -11,7 +11,7 @@ extension HttpClientResponseExtension on HttpClientResponse { Future get bodyBytes async { if (contentLength case final length when !length.isNegative) { int index = 0; - final bytes = Uint8List(length); + final Uint8List bytes = .new(length); await for (final e in this) { bytes.setAll(index, e); index += e.length; diff --git a/lib/extensions/isolate.dart b/lib/extensions/isolate.dart deleted file mode 100644 index 77afa77..0000000 --- a/lib/extensions/isolate.dart +++ /dev/null @@ -1,7 +0,0 @@ -import "dart:isolate"; - -extension IsolateExtension on Isolate { - static const String _mainIsolateDebugName = "main"; - - bool get isMain => debugName == _mainIsolateDebugName; -} diff --git a/lib/extensions/string.dart b/lib/extensions/string.dart index 8240a9b..815eebc 100644 --- a/lib/extensions/string.dart +++ b/lib/extensions/string.dart @@ -4,8 +4,6 @@ extension StringExtension on String { String capitalize([String? locale]) => toBeginningOfSentenceCase(this, locale); - int sumCodeUnits() => codeUnits.reduce((a, b) => a + b); - String intl({ String? desc, Map? examples, diff --git a/lib/main.dart b/lib/main.dart index e26422c..2d73f9c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,9 +11,9 @@ import "package:discloud/version.dart"; import "package:tint/tint.dart"; void main(Iterable arguments) async { - final context = CliContext(arguments); + final CliContext context = .new(arguments); - final runner = CliCommandRunner(); + final CliCommandRunner runner = .new(); late final ArgResults argResults; try { @@ -31,7 +31,7 @@ void main(Iterable arguments) async { ProcessSignal? firstReceivedSignal; - final signal = SignalWrapper( + final SignalWrapper signal = .new( .sigint, onSignal: (signal) { firstReceivedSignal ??= signal; @@ -49,7 +49,7 @@ void main(Iterable arguments) async { ); try { - await signal.run(() => runner.runCommand(argResults)); + await signal(() => runner.runCommand(argResults)); } catch (e, s) { context.printer ..error(resolveResponseMessage(e)) @@ -69,7 +69,7 @@ Discloud CLI v$packageVersion """; void _printCliHeader(ArgResults argResults) { - final buffer = StringBuffer() + final StringBuffer buffer = .new() ..writeAll(["discloud", ?argResults.commandName, "v$packageVersion"], " "); stderr.writeln(buffer.toString().bold()); diff --git a/lib/services/discloud/api_client.dart b/lib/services/discloud/api_client.dart index d1cba3d..21c59be 100644 --- a/lib/services/discloud/api_client.dart +++ b/lib/services/discloud/api_client.dart @@ -1,6 +1,6 @@ +import "dart:async"; import "dart:convert"; import "dart:io"; -import "dart:math"; import "package:discloud/cli/context.dart"; import "package:discloud/cli/disposable.dart"; @@ -13,7 +13,7 @@ import "package:discloud/services/discloud/utils.dart"; import "package:path/path.dart"; typedef VoidUploadProgressCallback = void Function(int processed); -typedef VoidUploadDoneCallback = void Function(); +typedef VoidUploadDoneCallback = FutureOr Function(); class DiscloudApiClient implements Disposable { static const _apiScheme = "https"; @@ -63,7 +63,7 @@ class DiscloudApiClient implements Disposable { factory DiscloudApiClient({HttpClient? client}) => DiscloudApiClient._(client: client ?? .new()); - const DiscloudApiClient._({required HttpClient client}) : _client = client; + const DiscloudApiClient._({required this._client}); final HttpClient _client; @@ -311,7 +311,7 @@ class DiscloudApiClient implements Disposable { await file.safeDelete(); - onUploadDone?.call(); + await onUploadDone?.call(); } Future _prepareRequest( diff --git a/lib/utils/messages.dart b/lib/utils/messages.dart index 8a21a58..270239d 100644 --- a/lib/utils/messages.dart +++ b/lib/utils/messages.dart @@ -4,7 +4,7 @@ import "package:discloud/services/discloud/exception.dart"; String resolveResponseMessage(T response) { switch (response) { case final Map r: - final buffer = StringBuffer(); + final StringBuffer buffer = .new(); buffer.writeAllCapitalized([?r["status"], ?r["message"]], ": "); @@ -15,7 +15,7 @@ String resolveResponseMessage(T response) { return buffer.toString(); case final DiscloudApiException e: - final buffer = StringBuffer("[Error ${e.code}]: ${e.message}"); + final StringBuffer buffer = .new("[Error ${e.code}]: ${e.message}"); if (e.localeList case final localeList? when localeList.isNotEmpty) { buffer.write(" (${localeList.join(", ")})"); diff --git a/lib/utils/progress.dart b/lib/utils/progress.dart index 037d014..e772d0a 100644 --- a/lib/utils/progress.dart +++ b/lib/utils/progress.dart @@ -21,10 +21,10 @@ String formatProgressMessage({ UnitDirection? direction, String prefixText = "Processing:", }) { - final buffer = StringBuffer("$prefixText "); + final StringBuffer buffer = .new(prefixText); if (speed case final speed?) { - buffer.writeAll([?direction, Bytes.bits(speed * 8), "/s "]); + buffer.writeAll([" ", ?direction, Bytes.bits(speed * 8), "/s "]); } buffer.write(percentFormatter.format(processed / total)); diff --git a/lib/utils/signal_wrapper.dart b/lib/utils/signal_wrapper.dart index da18cc3..8ccf706 100644 --- a/lib/utils/signal_wrapper.dart +++ b/lib/utils/signal_wrapper.dart @@ -16,7 +16,6 @@ abstract class SignalWrapper { onDispose: onDispose, onSignal: onSignal, completer: .new(), - subscriptions: [], ); factory SignalWrapper( @@ -35,21 +34,18 @@ abstract class SignalWrapper { bool get signed; - Future run(Future Function() fn); + Future call(Future Function() fn); } class _MultiSignalWrapper implements SignalWrapper { const _MultiSignalWrapper( this._signals, { - required Completer completer, - required List> subscriptions, + required this._completer, this.onSignal, this.onDispose, - }) : _completer = completer, - _subscriptions = subscriptions; + }); final Iterable _signals; - final List> _subscriptions; final Completer _completer; @override @@ -62,37 +58,37 @@ class _MultiSignalWrapper implements SignalWrapper { bool get signed => _completer.isCompleted; @override - // ignore: body_might_complete_normally_nullable - Future run(Future Function() fn) async { - for (final signal in _signals) { - _subscriptions.add(signal.watch().listen(_onData)); - } + Future call(Future Function() fn) async { + final futures = []; + final subscriptions = [ + for (final signal in _signals) + signal.watch().listen((signal) { + if (onSignal?.call(signal) case final Future f) futures.add(f); + if (!_completer.isCompleted) _completer.complete(signal); + }), + ]; try { final result = await Future.any([_completer.future, fn()]); - if (result is! ProcessSignal) return result as T; + if (result is T) return result; + return null; } catch (_) { rethrow; } finally { await onDispose?.call(); - await _subscriptions.cancel(); + await futures.wait; + await subscriptions.cancel(); } } - - void _onData(ProcessSignal signal) { - onSignal?.call(signal); - if (signed) return; - _completer.complete(signal); - } } class _SingleSignalWrapper implements SignalWrapper { const _SingleSignalWrapper( this._signal, { - required Completer completer, + required this._completer, this.onDispose, this.onSignal, - }) : _completer = completer; + }); final ProcessSignal _signal; final Completer _completer; @@ -107,8 +103,12 @@ class _SingleSignalWrapper implements SignalWrapper { bool get signed => _completer.isCompleted; @override - Future run(Future Function() fn) async { - final subscription = _signal.watch().listen(_onData); + Future call(Future Function() fn) async { + final futures = []; + final subscription = _signal.watch().listen((signal) { + if (onSignal?.call(signal) case final Future future) futures.add(future); + if (!_completer.isCompleted) _completer.complete(null); + }); try { return await Future.any([_completer.future, fn()]); @@ -116,13 +116,8 @@ class _SingleSignalWrapper implements SignalWrapper { rethrow; } finally { await onDispose?.call(); + await futures.wait; await subscription.cancel(); } } - - void _onData(ProcessSignal signal) { - onSignal?.call(signal); - if (signed) return; - _completer.complete(null); - } } diff --git a/lib/utils/speed_monitor.dart b/lib/utils/speed_monitor.dart index 5fb678e..cd30125 100644 --- a/lib/utils/speed_monitor.dart +++ b/lib/utils/speed_monitor.dart @@ -17,8 +17,10 @@ class SpeedMonitor implements Disposable { static const double _zero = 0; /// Creates a [SpeedMonitor] with a given [windowDuration]. - SpeedMonitor({this.windowDuration = const .new(seconds: 1)}) - : _samples = .new(); + factory SpeedMonitor() => ._(samples: .new()); + + const SpeedMonitor._({required this._samples}) + : windowDuration = const .new(seconds: 1); /// The duration of the sliding window used for speed calculation. final Duration windowDuration; diff --git a/pubspec.yaml b/pubspec.yaml index 1b3f571..16b505c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: none repository: https://github.com/discloud/cli-dart environment: - sdk: ^3.11.5 + sdk: ^3.12.0 dependencies: glob_zipper: @@ -25,7 +25,7 @@ dependencies: duration: ^4.0.3 freezed_annotation: ^3.1.0 intl: ^0.20.2 - json_annotation: ^4.11.0 + json_annotation: ^4.12.0 path: ^1.9.1 tabular: ^0.6.3+1 tint: ^2.0.1 @@ -36,7 +36,7 @@ dev_dependencies: freezed: ^3.2.5 inno_bundle: ^0.11.2 interpolation: ^2.1.2 - json_serializable: ^6.13.2 + json_serializable: ^6.14.0 lints: ^6.1.0 markdown: ^7.3.1 pub_semver: ^2.2.0