new & opt.
- new: support suspend and WOL #172 - opt.: `execWithPwd` when cancel - opt.: extentions
This commit is contained in:
@@ -164,7 +164,7 @@ class BackupPage extends StatelessWidget {
|
||||
backup.restore();
|
||||
context.pop();
|
||||
RebuildNodes.app.rebuild();
|
||||
Providers.reload();
|
||||
Pros.reload();
|
||||
},
|
||||
child: Text(l10n.ok),
|
||||
),
|
||||
|
||||
@@ -37,7 +37,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
Providers.docker.clear();
|
||||
Pros.docker.clear();
|
||||
_textController.dispose();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
if (client == null) {
|
||||
return;
|
||||
}
|
||||
Providers.docker
|
||||
Pros.docker
|
||||
..init(
|
||||
client,
|
||||
widget.spi.user,
|
||||
@@ -70,7 +70,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
context.showLoadingDialog();
|
||||
await Providers.docker.refresh();
|
||||
await Pros.docker.refresh();
|
||||
context.pop();
|
||||
},
|
||||
icon: const Icon(Icons.refresh),
|
||||
@@ -78,8 +78,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
],
|
||||
),
|
||||
body: _buildMain(),
|
||||
floatingActionButton:
|
||||
Providers.docker.error == null ? _buildFAB() : null,
|
||||
floatingActionButton: Pros.docker.error == null ? _buildFAB() : null,
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -156,7 +155,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
context.showLoadingDialog();
|
||||
final result = await Providers.docker.run(cmd);
|
||||
final result = await Pros.docker.run(cmd);
|
||||
context.pop();
|
||||
if (result != null) {
|
||||
context.showSnackBar(result.message ?? l10n.unknownError);
|
||||
@@ -182,7 +181,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
}
|
||||
|
||||
Widget _buildMain() {
|
||||
if (Providers.docker.error != null && Providers.docker.items == null) {
|
||||
if (Pros.docker.error != null && Pros.docker.items == null) {
|
||||
return SizedBox.expand(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -193,17 +192,17 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
size: 37,
|
||||
),
|
||||
const SizedBox(height: 27),
|
||||
Text(Providers.docker.error?.message ?? l10n.unknownError),
|
||||
Text(Pros.docker.error?.message ?? l10n.unknownError),
|
||||
const SizedBox(height: 27),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: _buildSolution(Providers.docker.error!),
|
||||
child: _buildSolution(Pros.docker.error!),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
if (Providers.docker.items == null || Providers.docker.images == null) {
|
||||
if (Pros.docker.items == null || Pros.docker.images == null) {
|
||||
return UIs.centerLoading;
|
||||
}
|
||||
|
||||
@@ -225,12 +224,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
ListTile(
|
||||
title: Text(l10n.imagesList),
|
||||
subtitle: Text(
|
||||
l10n.dockerImagesFmt(Providers.docker.images!.length),
|
||||
l10n.dockerImagesFmt(Pros.docker.images!.length),
|
||||
style: UIs.textGrey,
|
||||
),
|
||||
),
|
||||
];
|
||||
items.addAll(Providers.docker.images!.map(_buildImageItem));
|
||||
items.addAll(Pros.docker.images!.map(_buildImageItem));
|
||||
return Column(children: items);
|
||||
}
|
||||
|
||||
@@ -259,7 +258,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
final result = await Providers.docker.run(
|
||||
final result = await Pros.docker.run(
|
||||
'docker rmi ${e.id} -f',
|
||||
);
|
||||
if (result != null) {
|
||||
@@ -273,7 +272,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
}
|
||||
|
||||
Widget _buildLoading() {
|
||||
if (Providers.docker.runLog == null) return UIs.placeholder;
|
||||
if (Pros.docker.runLog == null) return UIs.placeholder;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: Column(
|
||||
@@ -282,7 +281,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
UIs.height13,
|
||||
Text(Providers.docker.runLog ?? '...'),
|
||||
Text(Pros.docker.runLog ?? '...'),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -323,8 +322,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(Providers.docker.edition ?? l10n.unknown),
|
||||
Text(Providers.docker.version ?? l10n.unknown),
|
||||
Text(Pros.docker.edition ?? l10n.unknown),
|
||||
Text(Pros.docker.version ?? l10n.unknown),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -335,12 +334,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
ListTile(
|
||||
title: Text(l10n.containerStatus),
|
||||
subtitle: Text(
|
||||
_buildPsCardSubtitle(Providers.docker.items!),
|
||||
_buildPsCardSubtitle(Pros.docker.items!),
|
||||
style: UIs.textGrey,
|
||||
),
|
||||
),
|
||||
];
|
||||
items.addAll(Providers.docker.items!.map(_buildPsItem));
|
||||
items.addAll(Pros.docker.items!.map(_buildPsItem));
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: items,
|
||||
@@ -372,7 +371,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
context.showLoadingDialog();
|
||||
await Providers.docker.delete(dItem.containerId);
|
||||
await Pros.docker.delete(dItem.containerId);
|
||||
context.pop();
|
||||
},
|
||||
child: Text(l10n.ok),
|
||||
@@ -382,17 +381,17 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
break;
|
||||
case DockerMenuType.start:
|
||||
context.showLoadingDialog();
|
||||
await Providers.docker.start(dItem.containerId);
|
||||
await Pros.docker.start(dItem.containerId);
|
||||
context.pop();
|
||||
break;
|
||||
case DockerMenuType.stop:
|
||||
context.showLoadingDialog();
|
||||
await Providers.docker.stop(dItem.containerId);
|
||||
await Pros.docker.stop(dItem.containerId);
|
||||
context.pop();
|
||||
break;
|
||||
case DockerMenuType.restart:
|
||||
context.showLoadingDialog();
|
||||
await Providers.docker.restart(dItem.containerId);
|
||||
await Pros.docker.restart(dItem.containerId);
|
||||
context.pop();
|
||||
break;
|
||||
case DockerMenuType.logs:
|
||||
@@ -441,7 +440,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
|
||||
Widget _buildEditHost() {
|
||||
final children = <Widget>[];
|
||||
if (Providers.docker.items!.isEmpty && Providers.docker.images!.isEmpty) {
|
||||
if (Pros.docker.items!.isEmpty && Pros.docker.images!.isEmpty) {
|
||||
children.add(Padding(
|
||||
padding: const EdgeInsets.fromLTRB(17, 17, 17, 0),
|
||||
child: Text(
|
||||
@@ -484,6 +483,6 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
void _onSaveDockerHost(String val) {
|
||||
context.pop();
|
||||
Stores.docker.put(widget.spi.id, val.trim());
|
||||
Providers.docker.refresh();
|
||||
Pros.docker.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,8 +368,8 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
||||
doUpdate(context);
|
||||
}
|
||||
await GetIt.I.allReady();
|
||||
await Providers.server.load();
|
||||
await Providers.server.refreshData();
|
||||
await Pros.server.load();
|
||||
await Pros.server.refreshData();
|
||||
if (!Analysis.enabled) {
|
||||
await Analysis.init();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class _HomePageState extends State<HomePage>
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
Providers.server.closeServer();
|
||||
Pros.server.closeServer();
|
||||
_pageController.dispose();
|
||||
}
|
||||
|
||||
@@ -84,20 +84,20 @@ class _HomePageState extends State<HomePage>
|
||||
switch (state) {
|
||||
case AppLifecycleState.resumed:
|
||||
_auth();
|
||||
if (!Providers.server.isAutoRefreshOn) {
|
||||
Providers.server.startAutoRefresh();
|
||||
if (!Pros.server.isAutoRefreshOn) {
|
||||
Pros.server.startAutoRefresh();
|
||||
}
|
||||
updateHomeWidget();
|
||||
break;
|
||||
case AppLifecycleState.paused:
|
||||
// Keep running in background on Android device
|
||||
if (isAndroid && Stores.setting.bgRun.fetch()) {
|
||||
if (Providers.app.moveBg) {
|
||||
if (Pros.app.moveBg) {
|
||||
BgRunMC.moveToBg();
|
||||
}
|
||||
} else {
|
||||
Providers.server.setDisconnected();
|
||||
Providers.server.stopAutoRefresh();
|
||||
Pros.server.setDisconnected();
|
||||
Pros.server.stopAutoRefresh();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -148,7 +148,7 @@ class _HomePageState extends State<HomePage>
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.refresh, size: 23),
|
||||
tooltip: 'Refresh',
|
||||
onPressed: () => Providers.server.refreshData(onlyFailed: true),
|
||||
onPressed: () => Pros.server.refreshData(onlyFailed: true),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -343,8 +343,8 @@ class _HomePageState extends State<HomePage>
|
||||
}
|
||||
updateHomeWidget();
|
||||
await GetIt.I.allReady();
|
||||
await Providers.server.load();
|
||||
await Providers.server.refreshData();
|
||||
await Pros.server.load();
|
||||
await Pros.server.refreshData();
|
||||
if (!Analysis.enabled) {
|
||||
Analysis.init();
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ class _PingPageState extends State<PingPage>
|
||||
return;
|
||||
}
|
||||
|
||||
if (Providers.server.serverOrder.isEmpty) {
|
||||
if (Pros.server.serverOrder.isEmpty) {
|
||||
context.showSnackBar(l10n.pingNoServer);
|
||||
return;
|
||||
}
|
||||
@@ -176,7 +176,7 @@ class _PingPageState extends State<PingPage>
|
||||
return;
|
||||
}
|
||||
|
||||
await Future.wait(Providers.server.servers.map((e) async {
|
||||
await Future.wait(Pros.server.servers.map((e) async {
|
||||
if (e.client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Providers.key.delete(widget.pki!);
|
||||
Pros.key.delete(widget.pki!);
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
@@ -135,9 +135,9 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||
final decrypted = await compute(decyptPem, [key, pwd]);
|
||||
final pki = PrivateKeyInfo(id: name, key: decrypted);
|
||||
if (widget.pki != null) {
|
||||
Providers.key.update(widget.pki!, pki);
|
||||
Pros.key.update(widget.pki!, pki);
|
||||
} else {
|
||||
Providers.key.add(pki);
|
||||
Pros.key.add(pki);
|
||||
}
|
||||
} catch (e) {
|
||||
context.showSnackBar(e.toString());
|
||||
|
||||
@@ -58,7 +58,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
||||
if (widget.spi?.pubKeyId == null) {
|
||||
_passwordController.text = widget.spi?.pwd ?? '';
|
||||
} else {
|
||||
_keyIdx.value = Providers.key.pkis.indexWhere(
|
||||
_keyIdx.value = Pros.key.pkis.indexWhere(
|
||||
(e) => e.id == widget.spi!.pubKeyId,
|
||||
);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Providers.server.delServer(widget.spi!.id);
|
||||
Pros.server.delServer(widget.spi!.id);
|
||||
context.pop();
|
||||
context.pop(true);
|
||||
},
|
||||
@@ -183,8 +183,8 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
||||
TagEditor(
|
||||
tags: _tags,
|
||||
onChanged: (p0) => _tags = p0,
|
||||
allTags: [...Providers.server.tags],
|
||||
onRenameTag: Providers.server.renameTag,
|
||||
allTags: [...Pros.server.tags],
|
||||
onRenameTag: Pros.server.renameTag,
|
||||
),
|
||||
_buildAuth(),
|
||||
ListTile(
|
||||
@@ -357,7 +357,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
||||
user: _usernameController.text,
|
||||
pwd: _passwordController.text.isEmpty ? null : _passwordController.text,
|
||||
pubKeyId: _keyIdx.value != null
|
||||
? Providers.key.pkis.elementAt(_keyIdx.value!).id
|
||||
? Pros.key.pkis.elementAt(_keyIdx.value!).id
|
||||
: null,
|
||||
tags: _tags,
|
||||
alterUrl: _altUrlController.text.isEmpty ? null : _altUrlController.text,
|
||||
@@ -365,9 +365,9 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
||||
);
|
||||
|
||||
if (widget.spi == null) {
|
||||
Providers.server.addServer(spi);
|
||||
Pros.server.addServer(spi);
|
||||
} else {
|
||||
Providers.server.updateServer(widget.spi!, spi);
|
||||
Pros.server.updateServer(widget.spi!, spi);
|
||||
}
|
||||
|
||||
context.pop();
|
||||
|
||||
@@ -92,8 +92,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
return child;
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async =>
|
||||
await Providers.server.refreshData(onlyFailed: true),
|
||||
onRefresh: () async => await Pros.server.refreshData(onlyFailed: true),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
@@ -245,22 +244,42 @@ class _ServerPageState extends State<ServerPage>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => srv.client?.execWithPwd(
|
||||
ShellFunc.shutdown.cmd,
|
||||
context: context,
|
||||
),
|
||||
icon: const Icon(Icons.power_off),
|
||||
onPressed: () async {
|
||||
if (Stores.first.showSuspendTip.fetch()) {
|
||||
await context.showRoundDialog(
|
||||
title: Text(l10n.attention),
|
||||
child: Text(l10n.suspendTip),
|
||||
);
|
||||
Stores.first.showSuspendTip.put(false);
|
||||
}
|
||||
srv.client?.execWithPwd(
|
||||
ShellFunc.suspend.exec,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.stop),
|
||||
tooltip: 'Suspend',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => srv.client?.execWithPwd(
|
||||
ShellFunc.reboot.cmd,
|
||||
ShellFunc.shutdown.exec,
|
||||
context: context,
|
||||
),
|
||||
icon: const Icon(Icons.refresh),
|
||||
icon: const Icon(Icons.power_off),
|
||||
tooltip: 'Shutdown',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => srv.client?.execWithPwd(
|
||||
ShellFunc.reboot.exec,
|
||||
context: context,
|
||||
),
|
||||
icon: const Icon(Icons.restart_alt),
|
||||
tooltip: 'Reboot',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => AppRoute.serverEdit(spi: srv.spi).go(context),
|
||||
icon: const Icon(Icons.edit),
|
||||
tooltip: l10n.edit,
|
||||
)
|
||||
],
|
||||
)
|
||||
@@ -305,7 +324,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
Widget? rightCorner;
|
||||
if (!(spi.autoConnect ?? true) && cs == ServerState.disconnected) {
|
||||
rightCorner = InkWell(
|
||||
onTap: () => Providers.server.refreshData(spi: spi),
|
||||
onTap: () => Pros.server.refreshData(spi: spi),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 7),
|
||||
child: Icon(
|
||||
@@ -456,8 +475,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
@override
|
||||
Future<void> afterFirstLayout(BuildContext context) async {
|
||||
await GetIt.I.allReady();
|
||||
await Providers.server.load();
|
||||
Providers.server.startAutoRefresh();
|
||||
await Pros.server.load();
|
||||
Pros.server.startAutoRefresh();
|
||||
}
|
||||
|
||||
List<String> _filterServers(ServerProvider pro) => pro.serverOrder
|
||||
|
||||
@@ -298,7 +298,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
onSelected: (int val) {
|
||||
_updateInterval.value = val;
|
||||
_setting.serverStatusUpdateInterval.put(val);
|
||||
Providers.server.startAutoRefresh();
|
||||
Pros.server.startAutoRefresh();
|
||||
if (val == 0) {
|
||||
context.showSnackBar(l10n.updateIntervalEqual0);
|
||||
}
|
||||
@@ -883,7 +883,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
child: Text(l10n.sureDelete(e)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Providers.server.delServer(e),
|
||||
onPressed: () => Pros.server.delServer(e),
|
||||
child: Text(l10n.ok),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -26,13 +26,13 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
if (Providers.server.serverOrder.isEmpty) {
|
||||
if (Pros.server.serverOrder.isEmpty) {
|
||||
return Center(child: Text(l10n.noServerAvailable));
|
||||
}
|
||||
return ReorderableListView.builder(
|
||||
footer: const SizedBox(height: 77),
|
||||
onReorder: (oldIndex, newIndex) => setState(() {
|
||||
Providers.server.serverOrder.move(
|
||||
Pros.server.serverOrder.move(
|
||||
oldIndex,
|
||||
newIndex,
|
||||
property: Stores.setting.serverOrder,
|
||||
@@ -41,13 +41,13 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),
|
||||
buildDefaultDragHandles: false,
|
||||
itemBuilder: (_, index) =>
|
||||
_buildItem(index, Providers.server.serverOrder[index]),
|
||||
itemCount: Providers.server.serverOrder.length,
|
||||
_buildItem(index, Pros.server.serverOrder[index]),
|
||||
itemCount: Pros.server.serverOrder.length,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildItem(int index, String id) {
|
||||
final spi = Providers.server.pick(id: id)?.spi;
|
||||
final spi = Pros.server.pick(id: id)?.spi;
|
||||
if (spi == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
return [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Providers.snippet.del(widget.snippet!);
|
||||
Pros.snippet.del(widget.snippet!);
|
||||
context.pop();
|
||||
},
|
||||
tooltip: l10n.delete,
|
||||
@@ -84,9 +84,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
note: note.isEmpty ? null : note,
|
||||
);
|
||||
if (widget.snippet != null) {
|
||||
Providers.snippet.update(widget.snippet!, snippet);
|
||||
Pros.snippet.update(widget.snippet!, snippet);
|
||||
} else {
|
||||
Providers.snippet.add(snippet);
|
||||
Pros.snippet.add(snippet);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
@@ -118,9 +118,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
onChanged: (p0) => setState(() {
|
||||
_tags = p0;
|
||||
}),
|
||||
allTags: [...Providers.server.tags],
|
||||
allTags: [...Pros.server.tags],
|
||||
onRenameTag: (old, n) => setState(() {
|
||||
Providers.server.renameTag(old, n);
|
||||
Pros.server.renameTag(old, n);
|
||||
}),
|
||||
),
|
||||
Input(
|
||||
|
||||
@@ -130,15 +130,15 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
final servers = await showDialog<List<Server>>(
|
||||
context: context,
|
||||
builder: (_) => TagPicker<Server>(
|
||||
items: Providers.server.servers.toList(),
|
||||
tags: Providers.server.tags.toSet(),
|
||||
items: Pros.server.servers.toList(),
|
||||
tags: Pros.server.tags.toSet(),
|
||||
),
|
||||
);
|
||||
if (servers == null) {
|
||||
return;
|
||||
}
|
||||
final ids = servers.map((e) => e.spi.id).toList();
|
||||
final results = await Providers.server.runSnippetsMulti(ids, [snippet]);
|
||||
final results = await Pros.server.runSnippetsMulti(ids, [snippet]);
|
||||
if (results.isNotEmpty) {
|
||||
// SERVER_NAME: RESULT
|
||||
final result = Map.fromIterables(
|
||||
|
||||
@@ -9,11 +9,11 @@ import 'package:toolbox/data/model/sftp/req.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
import 'package:toolbox/view/widget/omit_start_text.dart';
|
||||
import 'package:toolbox/view/widget/picker.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../../core/extension/numx.dart';
|
||||
import '../../../core/extension/stringx.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../data/model/app/path_with_prefix.dart';
|
||||
@@ -89,7 +89,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
(_path?.path ?? l10n.loadingFiles).omitStartStr(),
|
||||
OmitStartText(_path?.path ?? l10n.loadingFiles),
|
||||
_buildBtns(),
|
||||
],
|
||||
),
|
||||
@@ -275,7 +275,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
title: Text(l10n.upload),
|
||||
onTap: () async {
|
||||
context.pop();
|
||||
final ids = Providers.server.serverOrder;
|
||||
final ids = Pros.server.serverOrder;
|
||||
var idx = 0;
|
||||
await context.showRoundDialog(
|
||||
title: Text(l10n.server),
|
||||
@@ -289,7 +289,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
],
|
||||
);
|
||||
final id = ids[idx];
|
||||
final spi = Providers.server.pick(id: id)?.spi;
|
||||
final spi = Pros.server.pick(id: id)?.spi;
|
||||
if (spi == null) {
|
||||
return;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
if (remotePath == null) {
|
||||
return;
|
||||
}
|
||||
Providers.sftp.add(SftpReq(
|
||||
Pros.sftp.add(SftpReq(
|
||||
spi,
|
||||
'$remotePath/$fileName',
|
||||
file.absolute.path,
|
||||
|
||||
@@ -13,10 +13,10 @@ import 'package:toolbox/data/res/logger.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:toolbox/view/widget/omit_start_text.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../../core/extension/numx.dart';
|
||||
import '../../../core/extension/stringx.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
@@ -113,7 +113,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
(_status.path?.path ?? l10n.loadingFiles).omitStartStr(),
|
||||
OmitStartText(_status.path?.path ?? l10n.loadingFiles),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: children,
|
||||
@@ -162,7 +162,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
context.showSnackBar('remote path is null');
|
||||
return;
|
||||
}
|
||||
Providers.sftp.add(
|
||||
Pros.sftp.add(
|
||||
SftpReq(
|
||||
widget.spi,
|
||||
'$remotePath/${path.split('/').last}',
|
||||
@@ -362,14 +362,14 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
localPath,
|
||||
SftpReqType.download,
|
||||
);
|
||||
Providers.sftp.add(req, completer: completer);
|
||||
Pros.sftp.add(req, completer: completer);
|
||||
context.showLoadingDialog();
|
||||
await completer.future;
|
||||
context.pop();
|
||||
|
||||
final result = await AppRoute.editor(path: localPath).go<bool>(context);
|
||||
if (result != null && result) {
|
||||
Providers.sftp
|
||||
Pros.sftp
|
||||
.add(SftpReq(req.spi, remotePath, localPath, SftpReqType.upload));
|
||||
context.showSnackBar(l10n.added2List);
|
||||
}
|
||||
@@ -389,7 +389,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||
context.pop();
|
||||
final remotePath = _getRemotePath(name);
|
||||
|
||||
Providers.sftp.add(
|
||||
Pros.sftp.add(
|
||||
SftpReq(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
|
||||
@@ -141,7 +141,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Providers.sftp.cancel(id);
|
||||
Pros.sftp.cancel(id);
|
||||
context.pop();
|
||||
},
|
||||
child: Text(l10n.ok),
|
||||
|
||||
52
lib/view/widget/omit_start_text.dart
Normal file
52
lib/view/widget/omit_start_text.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class OmitStartText extends StatelessWidget {
|
||||
final String text;
|
||||
final int? maxLines;
|
||||
final TextStyle? style;
|
||||
final TextOverflow? overflow;
|
||||
|
||||
const OmitStartText(
|
||||
this.text, {
|
||||
Key? key,
|
||||
this.maxLines,
|
||||
this.style,
|
||||
this.overflow,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(builder: (context, size) {
|
||||
bool exceeded = false;
|
||||
int len = 0;
|
||||
for (; !exceeded && len < text.length; len++) {
|
||||
// Build the textspan
|
||||
var span = TextSpan(
|
||||
text: 'A' * 7 + text.substring(text.length - len),
|
||||
style: style ?? Theme.of(context).textTheme.bodyMedium,
|
||||
);
|
||||
|
||||
// Use a textpainter to determine if it will exceed max lines
|
||||
var tp = TextPainter(
|
||||
maxLines: maxLines ?? 1,
|
||||
textDirection: TextDirection.ltr,
|
||||
text: span,
|
||||
);
|
||||
|
||||
// trigger it to layout
|
||||
tp.layout(maxWidth: size.maxWidth);
|
||||
|
||||
// whether the text overflowed or not
|
||||
exceeded = tp.didExceedMaxLines;
|
||||
}
|
||||
|
||||
return Text(
|
||||
(exceeded ? '...' : '') + text.substring(text.length - len),
|
||||
overflow: overflow ?? TextOverflow.fade,
|
||||
softWrap: false,
|
||||
maxLines: maxLines ?? 1,
|
||||
style: style,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -99,14 +99,14 @@ void _onTapMoreBtns(
|
||||
final snippets = await showDialog<List<Snippet>>(
|
||||
context: context,
|
||||
builder: (_) => TagPicker<Snippet>(
|
||||
items: Providers.snippet.snippets,
|
||||
tags: Providers.server.tags.toSet(),
|
||||
items: Pros.snippet.snippets,
|
||||
tags: Pros.server.tags.toSet(),
|
||||
),
|
||||
);
|
||||
if (snippets == null) {
|
||||
return;
|
||||
}
|
||||
final result = await Providers.server.runSnippets(spi.id, snippets);
|
||||
final result = await Pros.server.runSnippets(spi.id, snippets);
|
||||
if (result != null && result.isNotEmpty) {
|
||||
context.showRoundDialog(
|
||||
title: Text(l10n.result),
|
||||
@@ -188,7 +188,7 @@ Future<void> _gotoSSH(
|
||||
}
|
||||
|
||||
bool _checkClient(BuildContext context, String id) {
|
||||
final server = Providers.server.pick(id: id);
|
||||
final server = Pros.server.pick(id: id);
|
||||
if (server == null || server.client == null) {
|
||||
context.showSnackBar(l10n.waitConnection);
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user