mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
opt.: ssh tab
This commit is contained in:
@@ -530,6 +530,12 @@ abstract class S {
|
|||||||
/// **'Extra args'**
|
/// **'Extra args'**
|
||||||
String get extraArgs;
|
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.
|
/// No description provided for @failed.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -230,6 +230,9 @@ class SDe extends S {
|
|||||||
@override
|
@override
|
||||||
String get extraArgs => 'Extra args';
|
String get extraArgs => 'Extra args';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fabOpenSSHSession => 'Klicken Sie auf die FAB, um eine Sitzung zu öffnen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get failed => 'Failed';
|
String get failed => 'Failed';
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,9 @@ class SEn extends S {
|
|||||||
@override
|
@override
|
||||||
String get extraArgs => 'Extra args';
|
String get extraArgs => 'Extra args';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fabOpenSSHSession => 'Click the FAB to open a session';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get failed => 'Failed';
|
String get failed => 'Failed';
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,9 @@ class SId extends S {
|
|||||||
@override
|
@override
|
||||||
String get extraArgs => 'Args ekstra';
|
String get extraArgs => 'Args ekstra';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fabOpenSSHSession => 'Klik FAB untuk membuka sesi';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get failed => 'Gagal';
|
String get failed => 'Gagal';
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,9 @@ class SZh extends S {
|
|||||||
@override
|
@override
|
||||||
String get extraArgs => '额外参数';
|
String get extraArgs => '额外参数';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fabOpenSSHSession => '点击右下FAB来开启新的SSH终端';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get failed => '失败';
|
String get failed => '失败';
|
||||||
|
|
||||||
@@ -1019,6 +1022,9 @@ class SZhTw extends SZh {
|
|||||||
@override
|
@override
|
||||||
String get extraArgs => '額外參數';
|
String get extraArgs => '額外參數';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fabOpenSSHSession => '點擊右下FAB來開啟新的SSH終端';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get failed => '失敗';
|
String get failed => '失敗';
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ class Server implements TagPickable {
|
|||||||
SSHClient? client;
|
SSHClient? client;
|
||||||
ServerState state;
|
ServerState state;
|
||||||
|
|
||||||
Server(this.spi, this.status, this.client, this.state);
|
Server(
|
||||||
|
this.spi,
|
||||||
|
this.status,
|
||||||
|
this.state, {
|
||||||
|
this.client,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool containsTag(String tag) {
|
bool containsTag(String tag) {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"experimentalFeature": "Experimentelles Feature",
|
"experimentalFeature": "Experimentelles Feature",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
"extraArgs": "Extra args",
|
"extraArgs": "Extra args",
|
||||||
|
"fabOpenSSHSession": "Klicken Sie auf die FAB, um eine Sitzung zu öffnen",
|
||||||
"failed": "Failed",
|
"failed": "Failed",
|
||||||
"feedback": "Feedback",
|
"feedback": "Feedback",
|
||||||
"feedbackOnGithub": "Wenn du Fragen hast, stelle diese bitte auf Github.",
|
"feedbackOnGithub": "Wenn du Fragen hast, stelle diese bitte auf Github.",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"experimentalFeature": "Experimental feature",
|
"experimentalFeature": "Experimental feature",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
"extraArgs": "Extra args",
|
"extraArgs": "Extra args",
|
||||||
|
"fabOpenSSHSession": "Click the FAB to open a session",
|
||||||
"failed": "Failed",
|
"failed": "Failed",
|
||||||
"feedback": "Feedback",
|
"feedback": "Feedback",
|
||||||
"feedbackOnGithub": "If you have any questions, please feedback on Github.",
|
"feedbackOnGithub": "If you have any questions, please feedback on Github.",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"experimentalFeature": "Fitur eksperimental",
|
"experimentalFeature": "Fitur eksperimental",
|
||||||
"export": "Ekspor",
|
"export": "Ekspor",
|
||||||
"extraArgs": "Args ekstra",
|
"extraArgs": "Args ekstra",
|
||||||
|
"fabOpenSSHSession": "Klik FAB untuk membuka sesi",
|
||||||
"failed": "Gagal",
|
"failed": "Gagal",
|
||||||
"feedback": "Masukan",
|
"feedback": "Masukan",
|
||||||
"feedbackOnGithub": "Jika Anda memiliki pertanyaan, silakan umpan balik tentang GitHub.",
|
"feedbackOnGithub": "Jika Anda memiliki pertanyaan, silakan umpan balik tentang GitHub.",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"experimentalFeature": "实验性功能",
|
"experimentalFeature": "实验性功能",
|
||||||
"export": "导出",
|
"export": "导出",
|
||||||
"extraArgs": "额外参数",
|
"extraArgs": "额外参数",
|
||||||
|
"fabOpenSSHSession": "点击右下FAB来开启新的SSH终端",
|
||||||
"failed": "失败",
|
"failed": "失败",
|
||||||
"feedback": "反馈",
|
"feedback": "反馈",
|
||||||
"feedbackOnGithub": "如果你有任何问题,请在GitHub反馈",
|
"feedbackOnGithub": "如果你有任何问题,请在GitHub反馈",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"experimentalFeature": "實驗性功能",
|
"experimentalFeature": "實驗性功能",
|
||||||
"export": "導出",
|
"export": "導出",
|
||||||
"extraArgs": "額外參數",
|
"extraArgs": "額外參數",
|
||||||
|
"fabOpenSSHSession": "點擊右下FAB來開啟新的SSH終端",
|
||||||
"failed": "失敗",
|
"failed": "失敗",
|
||||||
"feedback": "反饋",
|
"feedback": "反饋",
|
||||||
"feedbackOnGithub": "如果你有任何問題,請在GitHub反饋",
|
"feedbackOnGithub": "如果你有任何問題,請在GitHub反饋",
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
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/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/data/model/server/server.dart';
|
import 'package:toolbox/data/model/server/server.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/page/ssh/page.dart';
|
import 'package:toolbox/view/page/ssh/page.dart';
|
||||||
|
|
||||||
class SSHTabPage extends StatefulWidget {
|
class SSHTabPage extends StatefulWidget {
|
||||||
@@ -13,7 +16,9 @@ class SSHTabPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _SSHTabPageState extends State<SSHTabPage>
|
class _SSHTabPageState extends State<SSHTabPage>
|
||||||
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||||
final _tabIds = <String, SSHPage>{};
|
late final _tabIds = <String, Widget>{
|
||||||
|
l10n.add: _addPage,
|
||||||
|
};
|
||||||
final _tabKeys = <String, GlobalKey>{};
|
final _tabKeys = <String, GlobalKey>{};
|
||||||
late var _tabController = TabController(
|
late var _tabController = TabController(
|
||||||
length: _tabIds.length,
|
length: _tabIds.length,
|
||||||
@@ -30,22 +35,42 @@ class _SSHTabPageState extends State<SSHTabPage>
|
|||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
floatingActionButton: _buildFAB(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTabItem(String e) {
|
Widget _buildTabItem(String e) {
|
||||||
|
if (e == l10n.add) {
|
||||||
|
return Tab(child: Text(e));
|
||||||
|
}
|
||||||
return Tab(
|
return Tab(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(e),
|
Text(e),
|
||||||
IconButton(
|
UIs.width7,
|
||||||
icon: const Icon(Icons.close),
|
InkWell(
|
||||||
padding: EdgeInsets.zero,
|
borderRadius: BorderRadius.circular(17),
|
||||||
onPressed: () {
|
child: const Padding(padding: EdgeInsets.all(7), child: Icon(Icons.close, size: 17),),
|
||||||
_tabKeys[e]?.currentState?.dispose();
|
onTap: () async {
|
||||||
|
final confirm = await context.showRoundDialog<bool>(
|
||||||
|
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);
|
_tabIds.remove(e);
|
||||||
_refreshTabs();
|
_refreshTabs();
|
||||||
|
//_tabKeys[e]?.currentState?.dispose();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -53,45 +78,55 @@ class _SSHTabPageState extends State<SSHTabPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFAB() {
|
late final Widget _addPage = Center(
|
||||||
return FloatingActionButton(
|
child: Column(
|
||||||
onPressed: () async {
|
mainAxisSize: MainAxisSize.min,
|
||||||
final spi = (await context.showPickDialog<Server>(
|
children: [
|
||||||
items: Pros.server.servers.toList(),
|
Container(
|
||||||
name: (e) => e.spi.name,
|
decoration: BoxDecoration(
|
||||||
multi: false,
|
borderRadius: BorderRadius.circular(77),
|
||||||
))
|
color: Colors.white10,
|
||||||
?.first
|
),
|
||||||
.spi;
|
child: IconButton(
|
||||||
if (spi == null) {
|
padding: const EdgeInsets.all(17),
|
||||||
return;
|
onPressed: () async {
|
||||||
}
|
final spi = (await context.showPickDialog<Server>(
|
||||||
final name = () {
|
items: Pros.server.servers.toList(),
|
||||||
if (_tabIds.containsKey(spi.name)) {
|
name: (e) => e.spi.name,
|
||||||
return '${spi.name}(${_tabIds.length + 1})';
|
multi: false,
|
||||||
}
|
))
|
||||||
return spi.name;
|
?.first
|
||||||
}();
|
.spi;
|
||||||
final key = GlobalKey(debugLabel: 'sshTabPage_$name');
|
if (spi == null) {
|
||||||
_tabIds[name] = SSHPage(
|
return;
|
||||||
key: key,
|
}
|
||||||
spi: spi,
|
final name = () {
|
||||||
);
|
if (_tabIds.containsKey(spi.name)) {
|
||||||
_tabKeys[name] = key;
|
return '${spi.name}(${_tabIds.length + 1})';
|
||||||
_refreshTabs();
|
}
|
||||||
_tabController.animateTo(_tabIds.length - 1);
|
return spi.name;
|
||||||
},
|
}();
|
||||||
child: const Icon(Icons.add),
|
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() {
|
Widget _buildBody() {
|
||||||
if (_tabIds.isEmpty) {
|
|
||||||
return const Center(
|
|
||||||
child: Text('Click the fab to open a session'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return TabBarView(
|
return TabBarView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
children: _tabIds.values.toList(),
|
children: _tabIds.values.toList(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class ChoiceChipX<T> extends StatelessWidget {
|
|||||||
label: Text(label),
|
label: Text(label),
|
||||||
side: BorderSide.none,
|
side: BorderSide.none,
|
||||||
selected: state.selected(value),
|
selected: state.selected(value),
|
||||||
selectedColor: Theme.of(context).colorScheme.primary,
|
|
||||||
onSelected: state.onSelected(value),
|
onSelected: state.onSelected(value),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user