diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index bfad4aecf..41dfde727 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -530,6 +530,12 @@ abstract class S { /// **'Extra args'** String get extraArgs; + /// No description provided for @fabOpenSSHSession. + /// + /// In en, this message translates to: + /// **'Click the FAB to open a session'** + String get fabOpenSSHSession; + /// No description provided for @failed. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart index 9a98ee797..5c3d083ed 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart @@ -230,6 +230,9 @@ class SDe extends S { @override String get extraArgs => 'Extra args'; + @override + String get fabOpenSSHSession => 'Klicken Sie auf die FAB, um eine Sitzung zu öffnen'; + @override String get failed => 'Failed'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index daf352071..193be6ea6 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -230,6 +230,9 @@ class SEn extends S { @override String get extraArgs => 'Extra args'; + @override + String get fabOpenSSHSession => 'Click the FAB to open a session'; + @override String get failed => 'Failed'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart index 2a0c9c0f9..3fc2ab3e3 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_id.dart @@ -230,6 +230,9 @@ class SId extends S { @override String get extraArgs => 'Args ekstra'; + @override + String get fabOpenSSHSession => 'Klik FAB untuk membuka sesi'; + @override String get failed => 'Gagal'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index 097825c73..a6e5bd16c 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -230,6 +230,9 @@ class SZh extends S { @override String get extraArgs => '额外参数'; + @override + String get fabOpenSSHSession => '点击右下FAB来开启新的SSH终端'; + @override String get failed => '失败'; @@ -1019,6 +1022,9 @@ class SZhTw extends SZh { @override String get extraArgs => '額外參數'; + @override + String get fabOpenSSHSession => '點擊右下FAB來開啟新的SSH終端'; + @override String get failed => '失敗'; diff --git a/lib/data/model/server/server.dart b/lib/data/model/server/server.dart index 406e9bdb0..ef7045ef5 100644 --- a/lib/data/model/server/server.dart +++ b/lib/data/model/server/server.dart @@ -16,7 +16,12 @@ class Server implements TagPickable { SSHClient? client; ServerState state; - Server(this.spi, this.status, this.client, this.state); + Server( + this.spi, + this.status, + this.state, { + this.client, + }); @override bool containsTag(String tag) { diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 135b96a74..b72f6a7d6 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -72,6 +72,7 @@ "experimentalFeature": "Experimentelles Feature", "export": "Export", "extraArgs": "Extra args", + "fabOpenSSHSession": "Klicken Sie auf die FAB, um eine Sitzung zu öffnen", "failed": "Failed", "feedback": "Feedback", "feedbackOnGithub": "Wenn du Fragen hast, stelle diese bitte auf Github.", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 188d048ac..be56bc689 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -72,6 +72,7 @@ "experimentalFeature": "Experimental feature", "export": "Export", "extraArgs": "Extra args", + "fabOpenSSHSession": "Click the FAB to open a session", "failed": "Failed", "feedback": "Feedback", "feedbackOnGithub": "If you have any questions, please feedback on Github.", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 94961af17..bf2fb153d 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -72,6 +72,7 @@ "experimentalFeature": "Fitur eksperimental", "export": "Ekspor", "extraArgs": "Args ekstra", + "fabOpenSSHSession": "Klik FAB untuk membuka sesi", "failed": "Gagal", "feedback": "Masukan", "feedbackOnGithub": "Jika Anda memiliki pertanyaan, silakan umpan balik tentang GitHub.", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 5c909ae91..145456a2f 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -72,6 +72,7 @@ "experimentalFeature": "实验性功能", "export": "导出", "extraArgs": "额外参数", + "fabOpenSSHSession": "点击右下FAB来开启新的SSH终端", "failed": "失败", "feedback": "反馈", "feedbackOnGithub": "如果你有任何问题,请在GitHub反馈", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 1f68b667c..a5d78da68 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -72,6 +72,7 @@ "experimentalFeature": "實驗性功能", "export": "導出", "extraArgs": "額外參數", + "fabOpenSSHSession": "點擊右下FAB來開啟新的SSH終端", "failed": "失敗", "feedback": "反饋", "feedbackOnGithub": "如果你有任何問題,請在GitHub反饋", diff --git a/lib/view/page/ssh/tab.dart b/lib/view/page/ssh/tab.dart index 439849d29..2f5a2aa48 100644 --- a/lib/view/page/ssh/tab.dart +++ b/lib/view/page/ssh/tab.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:toolbox/core/extension/context/common.dart'; import 'package:toolbox/core/extension/context/dialog.dart'; +import 'package:toolbox/core/extension/context/locale.dart'; import 'package:toolbox/data/model/server/server.dart'; import 'package:toolbox/data/res/provider.dart'; +import 'package:toolbox/data/res/ui.dart'; import 'package:toolbox/view/page/ssh/page.dart'; class SSHTabPage extends StatefulWidget { @@ -13,7 +16,9 @@ class SSHTabPage extends StatefulWidget { class _SSHTabPageState extends State with TickerProviderStateMixin, AutomaticKeepAliveClientMixin { - final _tabIds = {}; + late final _tabIds = { + l10n.add: _addPage, + }; final _tabKeys = {}; late var _tabController = TabController( length: _tabIds.length, @@ -30,22 +35,42 @@ class _SSHTabPageState extends State isScrollable: true, ), body: _buildBody(), - floatingActionButton: _buildFAB(), ); } Widget _buildTabItem(String e) { + if (e == l10n.add) { + return Tab(child: Text(e)); + } return Tab( child: Row( children: [ Text(e), - IconButton( - icon: const Icon(Icons.close), - padding: EdgeInsets.zero, - onPressed: () { - _tabKeys[e]?.currentState?.dispose(); + UIs.width7, + InkWell( + borderRadius: BorderRadius.circular(17), + child: const Padding(padding: EdgeInsets.all(7), child: Icon(Icons.close, size: 17),), + onTap: () async { + final confirm = await context.showRoundDialog( + title: Text(l10n.attention), + child: Text('${l10n.close} SSH ${l10n.conn}($e) ?'), + actions: [ + TextButton( + onPressed: () => context.pop(true), + child: Text(l10n.ok, style: UIs.textRed), + ), + TextButton( + onPressed: () => context.pop(false), + child: Text(l10n.cancel), + ), + ], + ); + if (confirm != true) { + return; + } _tabIds.remove(e); _refreshTabs(); + //_tabKeys[e]?.currentState?.dispose(); }, ), ], @@ -53,45 +78,55 @@ class _SSHTabPageState extends State ); } - Widget _buildFAB() { - return FloatingActionButton( - onPressed: () async { - final spi = (await context.showPickDialog( - items: Pros.server.servers.toList(), - name: (e) => e.spi.name, - multi: false, - )) - ?.first - .spi; - if (spi == null) { - return; - } - final name = () { - if (_tabIds.containsKey(spi.name)) { - return '${spi.name}(${_tabIds.length + 1})'; - } - return spi.name; - }(); - final key = GlobalKey(debugLabel: 'sshTabPage_$name'); - _tabIds[name] = SSHPage( - key: key, - spi: spi, - ); - _tabKeys[name] = key; - _refreshTabs(); - _tabController.animateTo(_tabIds.length - 1); - }, - child: const Icon(Icons.add), - ); - } + late final Widget _addPage = Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(77), + color: Colors.white10, + ), + child: IconButton( + padding: const EdgeInsets.all(17), + onPressed: () async { + final spi = (await context.showPickDialog( + items: Pros.server.servers.toList(), + name: (e) => e.spi.name, + multi: false, + )) + ?.first + .spi; + if (spi == null) { + return; + } + final name = () { + if (_tabIds.containsKey(spi.name)) { + return '${spi.name}(${_tabIds.length + 1})'; + } + return spi.name; + }(); + final key = GlobalKey(debugLabel: 'sshTabPage_$name'); + _tabIds[name] = SSHPage( + key: key, + spi: spi, + ); + _tabKeys[name] = key; + _refreshTabs(); + _tabController.animateTo(_tabIds.length - 1); + }, + icon: const Icon(Icons.add), + ), + ), + UIs.height13, + Text(l10n.add), + ], + ), + ); Widget _buildBody() { - if (_tabIds.isEmpty) { - return const Center( - child: Text('Click the fab to open a session'), - ); - } return TabBarView( + physics: const NeverScrollableScrollPhysics(), controller: _tabController, children: _tabIds.values.toList(), ); diff --git a/lib/view/widget/choice_chip.dart b/lib/view/widget/choice_chip.dart index deb95bbae..0c293da5d 100644 --- a/lib/view/widget/choice_chip.dart +++ b/lib/view/widget/choice_chip.dart @@ -21,7 +21,6 @@ class ChoiceChipX extends StatelessWidget { label: Text(label), side: BorderSide.none, selected: state.selected(value), - selectedColor: Theme.of(context).colorScheme.primary, onSelected: state.onSelected(value), ), );