mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix & opt
fix: android in-app upgrade fmt: proj struct opt: fetch primaryColor
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:toolbox/core/extension/colorx.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/page/home.dart';
|
||||
|
||||
import 'core/utils/ui.dart';
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import '../data/res/build_data.dart';
|
||||
import '../data/service/app.dart';
|
||||
import '../generated/l10n.dart';
|
||||
import '../locator.dart';
|
||||
import 'utils.dart';
|
||||
import 'utils/ui.dart';
|
||||
|
||||
final _logger = Logger('UPDATE');
|
||||
|
||||
@@ -74,7 +74,7 @@ Future<void> doUpdate(BuildContext context, {bool force = false}) async {
|
||||
Future<void> _doUpdate(AppUpdate update, BuildContext context, S s) async {
|
||||
if (Platform.isAndroid) {
|
||||
await RUpgrade.upgrade(update.android,
|
||||
fileName: update.android.split('/').last);
|
||||
fileName: update.android.split('/').last, isAutoRequestInstall: true);
|
||||
} else if (Platform.isIOS) {
|
||||
await RUpgrade.upgradeFromAppStore('1586449703');
|
||||
} else {
|
||||
|
||||
23
lib/core/utils/misc.dart
Normal file
23
lib/core/utils/misc.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import '../../generated/l10n.dart';
|
||||
|
||||
Future<bool> shareFiles(BuildContext context, List<String> filePaths) async {
|
||||
for (final filePath in filePaths) {
|
||||
if (!await File(filePath).exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var text = '';
|
||||
if (filePaths.length == 1) {
|
||||
text = filePaths.first.split('/').last;
|
||||
} else {
|
||||
text = '${filePaths.length} ${S.of(context).files}';
|
||||
}
|
||||
final xfiles = filePaths.map((e) => XFile(e)).toList();
|
||||
await Share.shareXFiles(xfiles, text: 'ServerBox -> $text');
|
||||
return filePaths.isNotEmpty;
|
||||
}
|
||||
32
lib/core/utils/server.dart
Normal file
32
lib/core/utils/server.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
import '../../data/store/private_key.dart';
|
||||
import '../../locator.dart';
|
||||
|
||||
/// Must put this func out of any Class.
|
||||
/// Because of this function is called by [compute] in [ServerProvider.genClient].
|
||||
/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure
|
||||
List<SSHKeyPair> loadIndentity(String key) {
|
||||
return SSHKeyPair.fromPem(key);
|
||||
}
|
||||
|
||||
Future<SSHClient> genClient(ServerPrivateInfo spi) async {
|
||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||
if (spi.pubKeyId == null) {
|
||||
return SSHClient(
|
||||
socket,
|
||||
username: spi.user,
|
||||
onPasswordRequest: () => spi.pwd,
|
||||
);
|
||||
}
|
||||
final key = locator<PrivateKeyStore>().get(spi.pubKeyId!);
|
||||
return SSHClient(
|
||||
socket,
|
||||
username: spi.user,
|
||||
identities: await compute(loadIndentity, key.privateKey),
|
||||
);
|
||||
}
|
||||
@@ -1,22 +1,13 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:toolbox/core/persistant_store.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/view/widget/card_dialog.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:toolbox/core/extension/stringx.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
/// Must put this func out of any Class.
|
||||
/// Because of this function is called by [compute] in [ServerProvider.genClient].
|
||||
/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure
|
||||
List<SSHKeyPair> loadIndentity(String key) {
|
||||
return SSHKeyPair.fromPem(key);
|
||||
}
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../view/widget/card_dialog.dart';
|
||||
import '../persistant_store.dart';
|
||||
|
||||
bool isDarkMode(BuildContext context) =>
|
||||
Theme.of(context).brightness == Brightness.dark;
|
||||
@@ -79,37 +70,6 @@ void setTransparentNavigationBar(BuildContext context) {
|
||||
}
|
||||
}
|
||||
|
||||
String tabTitleName(BuildContext context, int i) {
|
||||
final s = S.of(context);
|
||||
switch (i) {
|
||||
case 0:
|
||||
return s.server;
|
||||
case 1:
|
||||
return s.convert;
|
||||
case 2:
|
||||
return s.ping;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> shareFiles(BuildContext context, List<String> filePaths) async {
|
||||
for (final filePath in filePaths) {
|
||||
if (!await File(filePath).exists()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var text = '';
|
||||
if (filePaths.length == 1) {
|
||||
text = filePaths.first.split('/').last;
|
||||
} else {
|
||||
text = '${filePaths.length} ${S.of(context).files}';
|
||||
}
|
||||
final xfiles = filePaths.map((e) => XFile(e)).toList();
|
||||
await Share.shareXFiles(xfiles, text: 'ServerBox -> $text');
|
||||
return filePaths.isNotEmpty;
|
||||
}
|
||||
|
||||
Widget buildPopuopMenu(
|
||||
{required List<PopupMenuEntry> items,
|
||||
required Function(dynamic) onSelected}) {
|
||||
@@ -127,3 +87,17 @@ Widget buildPopuopMenu(
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String tabTitleName(BuildContext context, int i) {
|
||||
final s = S.of(context);
|
||||
switch (i) {
|
||||
case 0:
|
||||
return s.server;
|
||||
case 1:
|
||||
return s.convert;
|
||||
case 2:
|
||||
return s.ping;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import '../../core/extension/uint8list.dart';
|
||||
import '../../core/provider_base.dart';
|
||||
import '../../core/utils.dart';
|
||||
import '../../core/utils/server.dart';
|
||||
import '../../locator.dart';
|
||||
import '../model/server/cpu_status.dart';
|
||||
import '../model/server/disk_info.dart';
|
||||
@@ -16,24 +15,11 @@ import '../model/server/server.dart';
|
||||
import '../model/server/server_private_info.dart';
|
||||
import '../model/server/snippet.dart';
|
||||
import '../model/server/tcp_status.dart';
|
||||
import '../res/server_cmd.dart';
|
||||
import '../res/status.dart';
|
||||
import '../store/private_key.dart';
|
||||
import '../store/server.dart';
|
||||
import '../store/setting.dart';
|
||||
|
||||
const seperator = 'A====A';
|
||||
const shellCmd = "export LANG=en_US.utf-8 \necho '$seperator' \n"
|
||||
"cat /proc/net/dev && date +%s \necho $seperator \n "
|
||||
"cat /etc/os-release | grep PRETTY_NAME \necho $seperator \n"
|
||||
"cat /proc/stat | grep cpu \necho $seperator \n"
|
||||
"uptime \necho $seperator \n"
|
||||
"cat /proc/net/snmp \necho $seperator \n"
|
||||
"df -h \necho $seperator \n"
|
||||
"cat /proc/meminfo \necho $seperator \n"
|
||||
"cat /sys/class/thermal/thermal_zone*/type \necho $seperator \n"
|
||||
"cat /sys/class/thermal/thermal_zone*/temp";
|
||||
const shellPath = '.serverbox.sh';
|
||||
|
||||
class ServerProvider extends BusyProvider {
|
||||
List<Server> _servers = [];
|
||||
List<Server> get servers => _servers;
|
||||
@@ -54,18 +40,6 @@ class ServerProvider extends BusyProvider {
|
||||
return Server(spi, initStatus, null, ServerConnectionState.disconnected);
|
||||
}
|
||||
|
||||
Future<SSHClient> genClient(ServerPrivateInfo spi) async {
|
||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||
if (spi.pubKeyId == null) {
|
||||
return SSHClient(socket,
|
||||
username: spi.user, onPasswordRequest: () => spi.pwd);
|
||||
}
|
||||
final key = locator<PrivateKeyStore>().get(spi.pubKeyId!);
|
||||
return SSHClient(socket,
|
||||
username: spi.user,
|
||||
identities: await compute(loadIndentity, key.privateKey));
|
||||
}
|
||||
|
||||
Future<void> refreshData({ServerPrivateInfo? spi}) async {
|
||||
if (spi != null) {
|
||||
_getData(spi);
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 201;
|
||||
static const int build = 202;
|
||||
static const String engine =
|
||||
"Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (7 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n";
|
||||
static const String buildAt = "2023-01-31 17:36:05.286138";
|
||||
"Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (8 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n";
|
||||
static const String buildAt = "2023-02-01 10:55:03.386055";
|
||||
static const int modifications = 5;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
|
||||
Color get primaryColor => Color(locator<SettingStore>().primaryColor.fetch()!);
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../locator.dart';
|
||||
import '../store/setting.dart';
|
||||
|
||||
final _primaryColor = locator<SettingStore>().primaryColor.listenable();
|
||||
|
||||
class PrimaryColor extends StatelessWidget {
|
||||
final Widget Function(BuildContext context, Color primaryColor) builder;
|
||||
|
||||
const PrimaryColor({Key? key, required this.builder}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<int>(
|
||||
builder: (context, c, child) => builder(context, Color(c)),
|
||||
valueListenable: _primaryColor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DynamicColor {
|
||||
/// 白天模式显示的颜色
|
||||
|
||||
12
lib/data/res/server_cmd.dart
Normal file
12
lib/data/res/server_cmd.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
const seperator = 'A====A';
|
||||
const shellCmd = "export LANG=en_US.utf-8 \necho '$seperator' \n"
|
||||
"cat /proc/net/dev && date +%s \necho $seperator \n "
|
||||
"cat /etc/os-release | grep PRETTY_NAME \necho $seperator \n"
|
||||
"cat /proc/stat | grep cpu \necho $seperator \n"
|
||||
"uptime \necho $seperator \n"
|
||||
"cat /proc/net/snmp \necho $seperator \n"
|
||||
"df -h \necho $seperator \n"
|
||||
"cat /proc/meminfo \necho $seperator \n"
|
||||
"cat /sys/class/thermal/thermal_zone*/type \necho $seperator \n"
|
||||
"cat /sys/class/thermal/thermal_zone*/temp";
|
||||
const shellPath = '.serverbox.sh';
|
||||
@@ -4,17 +4,18 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/core/extension/colorx.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/store/private_key.dart';
|
||||
import 'package:toolbox/data/store/server.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/data/store/snippet.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
|
||||
import '../../core/extension/colorx.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/app/backup.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../data/store/private_key.dart';
|
||||
import '../../data/store/server.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../data/store/snippet.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
|
||||
const backupFormatVersion = 1;
|
||||
|
||||
@@ -67,29 +68,32 @@ class BackupPage extends StatelessWidget {
|
||||
|
||||
Widget _buildCard(String text, IconData icon, MediaQueryData media,
|
||||
FutureOr Function() onTap) {
|
||||
final priColor = primaryColor;
|
||||
final textColor = priColor.isBrightColor ? Colors.black : Colors.white;
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(37), color: priColor),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: textColor,
|
||||
return PrimaryColor(
|
||||
builder: ((context, pColor) {
|
||||
final textColor = pColor.isBrightColor ? Colors.black : Colors.white;
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(37), color: pColor),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: textColor,
|
||||
),
|
||||
const SizedBox(width: 7),
|
||||
Text(text, style: TextStyle(color: textColor)),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 7),
|
||||
Text(text, style: TextStyle(color: textColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../widget/input_field.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
|
||||
class ConvertPage extends StatefulWidget {
|
||||
const ConvertPage({Key? key}) : super(key: key);
|
||||
@@ -104,75 +105,78 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
'URL $encode',
|
||||
'URL $decode'
|
||||
];
|
||||
return RoundRectCard(
|
||||
ExpansionTile(
|
||||
tilePadding: const EdgeInsets.only(left: 7, right: 27),
|
||||
childrenPadding: EdgeInsets.zero,
|
||||
title: Row(
|
||||
children: [
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||
child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown),
|
||||
onPressed: () {
|
||||
final temp = _textEditingController.text;
|
||||
_textEditingController.text = _textEditingControllerResult.text;
|
||||
_textEditingControllerResult.text = temp;
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor),
|
||||
),
|
||||
child: Icon(Icons.copy, semanticLabel: _s.copy),
|
||||
onPressed: () => Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: _textEditingControllerResult.text == ''
|
||||
? ' '
|
||||
: _textEditingControllerResult.text),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
trailing: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
return PrimaryColor(builder: (context, primaryColor) {
|
||||
return RoundRectCard(
|
||||
ExpansionTile(
|
||||
tilePadding: const EdgeInsets.only(left: 7, right: 27),
|
||||
childrenPadding: EdgeInsets.zero,
|
||||
title: Row(
|
||||
children: [
|
||||
Text(
|
||||
typeOption[_typeOptionIndex],
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primaryColor),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||
child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown),
|
||||
onPressed: () {
|
||||
final temp = _textEditingController.text;
|
||||
_textEditingController.text =
|
||||
_textEditingControllerResult.text;
|
||||
_textEditingControllerResult.text = temp;
|
||||
},
|
||||
),
|
||||
Text(
|
||||
_s.currentMode,
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(fontSize: 9.0, color: Colors.grey),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor),
|
||||
),
|
||||
child: Icon(Icons.copy, semanticLabel: _s.copy),
|
||||
onPressed: () => Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: _textEditingControllerResult.text == ''
|
||||
? ' '
|
||||
: _textEditingControllerResult.text),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
children: typeOption
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
title: Text(
|
||||
e,
|
||||
trailing: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
typeOption[_typeOptionIndex],
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: _theme.textTheme.bodyMedium?.color?.withAlpha(177),
|
||||
),
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primaryColor),
|
||||
),
|
||||
trailing: _buildRadio(typeOption.indexOf(e)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
Text(
|
||||
_s.currentMode,
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(fontSize: 9.0, color: Colors.grey),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
children: typeOption
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
title: Text(
|
||||
e,
|
||||
style: TextStyle(
|
||||
color: _theme.textTheme.bodyMedium?.color?.withAlpha(177),
|
||||
),
|
||||
),
|
||||
trailing: _buildRadio(typeOption.indexOf(e)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildResult() {
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/docker/ps.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/provider/docker.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/error.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/data/store/docker.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/center_loading.dart';
|
||||
import 'package:toolbox/view/widget/two_line_text.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
import 'package:toolbox/view/widget/url_text.dart';
|
||||
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/docker/ps.dart';
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
import '../../data/provider/docker.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/error.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../data/res/menu.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/docker.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/center_loading.dart';
|
||||
import '../widget/dropdown_menu.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
import '../widget/url_text.dart';
|
||||
|
||||
class DockerManagePage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
|
||||
@@ -2,31 +2,31 @@ import 'package:after_layout/after_layout.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:toolbox/core/analysis.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/core/update.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/app/navigation_item.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/icon.dart';
|
||||
import 'package:toolbox/data/res/tab.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/page/backup.dart';
|
||||
import 'package:toolbox/view/page/convert.dart';
|
||||
import 'package:toolbox/view/page/debug.dart';
|
||||
import 'package:toolbox/view/page/ping.dart';
|
||||
import 'package:toolbox/view/page/private_key/list.dart';
|
||||
import 'package:toolbox/view/page/server/tab.dart';
|
||||
import 'package:toolbox/view/page/setting.dart';
|
||||
import 'package:toolbox/view/page/sftp/downloaded.dart';
|
||||
import 'package:toolbox/view/page/snippet/list.dart';
|
||||
import 'package:toolbox/view/widget/url_text.dart';
|
||||
|
||||
import '../../core/analysis.dart';
|
||||
import '../../core/route.dart';
|
||||
import '../../core/update.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/app/navigation_item.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/build_data.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../data/res/icon.dart';
|
||||
import '../../data/res/tab.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/url_text.dart';
|
||||
import 'backup.dart';
|
||||
import 'convert.dart';
|
||||
import 'debug.dart';
|
||||
import 'ping.dart';
|
||||
import 'private_key/list.dart';
|
||||
import 'server/tab.dart';
|
||||
import 'setting.dart';
|
||||
import 'sftp/downloaded.dart';
|
||||
import 'snippet/list.dart';
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({Key? key, required this.primaryColor}) : super(key: key);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/uint8list.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/ping_result.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../core/extension/uint8list.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/server/ping_result.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/input_field.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
|
||||
final doaminReg =
|
||||
RegExp(r'^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$');
|
||||
@@ -88,29 +89,34 @@ class _PingPageState extends State<PingPage>
|
||||
Widget _buildResultItem(PingResult result) {
|
||||
final unknown = s.unknown;
|
||||
final ms = s.ms;
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||
title: Text(
|
||||
result.serverName,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: primaryColor,
|
||||
return PrimaryColor(
|
||||
builder: ((context, primaryColor) {
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||
title: Text(
|
||||
result.serverName,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
_buildPingSummary(result, unknown, ms),
|
||||
style: textSize11,
|
||||
),
|
||||
trailing: Text(
|
||||
'${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
_buildPingSummary(result, unknown, ms),
|
||||
style: textSize11,
|
||||
),
|
||||
trailing: Text(
|
||||
'${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/pkg/upgrade_info.dart';
|
||||
import 'package:toolbox/data/model/server/dist.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/provider/pkg.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/center_loading.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
import 'package:toolbox/view/widget/two_line_text.dart';
|
||||
|
||||
import '../../data/model/pkg/upgrade_info.dart';
|
||||
import '../../data/model/server/dist.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
import '../../data/provider/pkg.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/center_loading.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
|
||||
class PkgManagePage extends StatefulWidget {
|
||||
const PkgManagePage(this.spi, {Key? key}) : super(key: key);
|
||||
|
||||
@@ -3,13 +3,14 @@ import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/provider/private_key.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/private_key_info.dart';
|
||||
import '../../../data/provider/private_key.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/input_decoration.dart';
|
||||
|
||||
const _format = 'text/plain';
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late MediaQueryData _media;
|
||||
late S _s;
|
||||
late Color pColor;
|
||||
bool _showDistLogo = true;
|
||||
|
||||
@override
|
||||
@@ -38,7 +37,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
_media = MediaQuery.of(context);
|
||||
_s = S.of(context);
|
||||
_showDistLogo = locator<SettingStore>().showDistLogo.fetch()!;
|
||||
pColor = primaryColor;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -175,12 +173,14 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
Widget _buildProgress(double percent) {
|
||||
if (percent > 100) percent = 100;
|
||||
final percentWithinOne = percent / 100;
|
||||
return LinearProgressIndicator(
|
||||
value: percentWithinOne,
|
||||
minHeight: 7,
|
||||
backgroundColor: progressColor.resolve(context),
|
||||
color: pColor,
|
||||
);
|
||||
return PrimaryColor(builder: (context, primaryColor) {
|
||||
return LinearProgressIndicator(
|
||||
value: percentWithinOne,
|
||||
minHeight: 7,
|
||||
backgroundColor: progressColor.resolve(context),
|
||||
color: primaryColor,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildUpTimeAndSys(ServerStatus ss) {
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import 'package:after_layout/after_layout.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/provider/private_key.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/store/private_key.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/page/private_key/edit.dart';
|
||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/private_key_info.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
import '../../../data/provider/private_key.dart';
|
||||
import '../../../data/provider/server.dart';
|
||||
import '../../../data/res/color.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../data/store/private_key.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/input_decoration.dart';
|
||||
import '../private_key/edit.dart';
|
||||
|
||||
class ServerEditPage extends StatefulWidget {
|
||||
const ServerEditPage({Key? key, this.spi}) : super(key: key);
|
||||
@@ -104,8 +105,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: _nameFocus,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_ipFocus),
|
||||
decoration: buildDecoration(_s.name,
|
||||
icon: Icons.info, hint: _s.exampleName),
|
||||
decoration: buildDecoration(
|
||||
_s.name,
|
||||
icon: Icons.info,
|
||||
hint: _s.exampleName,
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: _ipController,
|
||||
@@ -114,16 +118,22 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
focusNode: _ipFocus,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(_s.host,
|
||||
icon: Icons.storage, hint: 'example.com'),
|
||||
decoration: buildDecoration(
|
||||
_s.host,
|
||||
icon: Icons.storage,
|
||||
hint: 'example.com',
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: _portController,
|
||||
keyboardType: TextInputType.number,
|
||||
focusNode: _portFocus,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus),
|
||||
decoration: buildDecoration(_s.port,
|
||||
icon: Icons.format_list_numbered, hint: '22'),
|
||||
decoration: buildDecoration(
|
||||
_s.port,
|
||||
icon: Icons.format_list_numbered,
|
||||
hint: '22',
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: _usernameController,
|
||||
@@ -131,16 +141,20 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
focusNode: _usernameFocus,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(_s.user,
|
||||
icon: Icons.account_box, hint: 'root'),
|
||||
decoration: buildDecoration(
|
||||
_s.user,
|
||||
icon: Icons.account_box,
|
||||
hint: 'root',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
Row(
|
||||
children: [
|
||||
Text(_s.keyAuth),
|
||||
Switch(
|
||||
value: usePublicKey,
|
||||
onChanged: (val) => setState(() => usePublicKey = val)),
|
||||
value: usePublicKey,
|
||||
onChanged: (val) => setState(() => usePublicKey = val),
|
||||
),
|
||||
],
|
||||
),
|
||||
!usePublicKey
|
||||
@@ -148,8 +162,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: buildDecoration(_s.pwd,
|
||||
icon: Icons.password, hint: _s.pwd),
|
||||
decoration: buildDecoration(
|
||||
_s.pwd,
|
||||
icon: Icons.password,
|
||||
hint: _s.pwd,
|
||||
),
|
||||
onSubmitted: (_) => {},
|
||||
)
|
||||
: const SizedBox(),
|
||||
@@ -164,9 +181,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
final tiles = key.infos
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(e.id, textAlign: TextAlign.start),
|
||||
trailing: _buildRadio(key.infos.indexOf(e), e)),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(e.id, textAlign: TextAlign.start),
|
||||
trailing: _buildRadio(key.infos.indexOf(e), e),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
tiles.add(
|
||||
@@ -176,23 +194,25 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: () => AppRoute(
|
||||
const PrivateKeyEditPage(),
|
||||
'private key edit page')
|
||||
.go(context),
|
||||
const PrivateKeyEditPage(),
|
||||
'private key edit page',
|
||||
).go(context),
|
||||
),
|
||||
),
|
||||
);
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
iconColor: primaryColor,
|
||||
tilePadding: EdgeInsets.zero,
|
||||
childrenPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
_s.choosePrivateKey,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
children: tiles,
|
||||
);
|
||||
return PrimaryColor(builder: ((context, primaryColor) {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
iconColor: primaryColor,
|
||||
tilePadding: EdgeInsets.zero,
|
||||
childrenPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
_s.choosePrivateKey,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
children: tiles,
|
||||
);
|
||||
}));
|
||||
},
|
||||
)
|
||||
: const SizedBox()
|
||||
|
||||
@@ -3,32 +3,32 @@ import 'package:circle_chart/circle_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/server.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_status.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/provider/snippet.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/page/pkg.dart';
|
||||
import 'package:toolbox/view/page/docker.dart';
|
||||
import 'package:toolbox/view/page/server/detail.dart';
|
||||
import 'package:toolbox/view/page/server/edit.dart';
|
||||
import 'package:toolbox/view/page/sftp/view.dart';
|
||||
import 'package:toolbox/view/page/snippet/edit.dart';
|
||||
import 'package:toolbox/view/page/ssh.dart';
|
||||
import 'package:toolbox/view/widget/picker.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/server.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
import '../../../data/model/server/server_status.dart';
|
||||
import '../../../data/provider/server.dart';
|
||||
import '../../../data/provider/snippet.dart';
|
||||
import '../../../data/res/color.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../data/res/menu.dart';
|
||||
import '../../../data/res/url.dart';
|
||||
import '../../../data/store/setting.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/dropdown_menu.dart';
|
||||
import '../../widget/picker.dart';
|
||||
import '../../widget/round_rect_card.dart';
|
||||
import '../../widget/url_text.dart';
|
||||
import '../docker.dart';
|
||||
import '../pkg.dart';
|
||||
import '../sftp/view.dart';
|
||||
import '../snippet/edit.dart';
|
||||
import '../ssh.dart';
|
||||
import 'detail.dart';
|
||||
import 'edit.dart';
|
||||
|
||||
class ServerPage extends StatefulWidget {
|
||||
const ServerPage({Key? key}) : super(key: key);
|
||||
@@ -41,7 +41,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
||||
late MediaQueryData _media;
|
||||
late ThemeData _theme;
|
||||
late Color _primaryColor;
|
||||
late ServerProvider _serverProvider;
|
||||
late SettingStore _settingStore;
|
||||
late S _s;
|
||||
@@ -58,7 +57,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
super.didChangeDependencies();
|
||||
_media = MediaQuery.of(context);
|
||||
_theme = Theme.of(context);
|
||||
_primaryColor = primaryColor;
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@@ -94,9 +92,10 @@ class _ServerPageState extends State<ServerPage>
|
||||
return Scaffold(
|
||||
body: child,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () =>
|
||||
AppRoute(const ServerEditPage(), 'Add server info page')
|
||||
.go(context),
|
||||
onPressed: () => AppRoute(
|
||||
const ServerEditPage(),
|
||||
'Add server info page',
|
||||
).go(context),
|
||||
tooltip: _s.addAServer,
|
||||
heroTag: 'server page fab',
|
||||
child: const Icon(Icons.add),
|
||||
@@ -353,12 +352,16 @@ class _ServerPageState extends State<ServerPage>
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: CircleChart(
|
||||
progressColor: _primaryColor,
|
||||
progressNumber: percent,
|
||||
maxNumber: 100,
|
||||
width: 53,
|
||||
height: 53,
|
||||
child: PrimaryColor(
|
||||
builder: (context, primaryColor) {
|
||||
return CircleChart(
|
||||
progressColor: primaryColor,
|
||||
progressNumber: percent,
|
||||
maxNumber: 100,
|
||||
width: 53,
|
||||
height: 53,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
@@ -404,8 +407,10 @@ class _ServerPageState extends State<ServerPage>
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.choose,
|
||||
buildPicker(provider.snippets.map((e) => Text(e.name)).toList(),
|
||||
(idx) => snippet = provider.snippets[idx]),
|
||||
buildPicker(
|
||||
provider.snippets.map((e) => Text(e.name)).toList(),
|
||||
(idx) => snippet = provider.snippets[idx],
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
@@ -418,8 +423,9 @@ class _ServerPageState extends State<ServerPage>
|
||||
Text(result ?? _s.error, style: textSize13),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(_s.ok))
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(_s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/update.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/provider/app.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/tab.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../core/update.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/provider/app.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/build_data.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/font_style.dart';
|
||||
import '../../data/res/tab.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
|
||||
class SettingPage extends StatefulWidget {
|
||||
const SettingPage({Key? key}) : super(key: key);
|
||||
@@ -25,7 +26,6 @@ class _SettingPageState extends State<SettingPage> {
|
||||
late final SettingStore _setting;
|
||||
late int _selectedColorValue;
|
||||
late int _launchPageIdx;
|
||||
late Color priColor;
|
||||
late final ServerProvider _serverProvider;
|
||||
late MediaQueryData _media;
|
||||
late ThemeData _theme;
|
||||
@@ -36,7 +36,6 @@ class _SettingPageState extends State<SettingPage> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
priColor = primaryColor;
|
||||
_media = MediaQuery.of(context);
|
||||
_theme = Theme.of(context);
|
||||
_s = S.of(context);
|
||||
@@ -57,15 +56,19 @@ class _SettingPageState extends State<SettingPage> {
|
||||
appBar: AppBar(
|
||||
title: Text(_s.setting),
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(17),
|
||||
children: [
|
||||
_buildAppColorPreview(),
|
||||
_buildUpdateInterval(),
|
||||
_buildCheckUpdate(),
|
||||
_buildLaunchPage(),
|
||||
_buildDistLogoSwitch(),
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
body: PrimaryColor(
|
||||
builder: (context, primaryColor) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(17),
|
||||
children: [
|
||||
_buildAppColorPreview(primaryColor),
|
||||
_buildUpdateInterval(primaryColor),
|
||||
_buildCheckUpdate(),
|
||||
_buildLaunchPage(primaryColor),
|
||||
_buildDistLogoSwitch(),
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -110,7 +113,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildUpdateInterval() {
|
||||
Widget _buildUpdateInterval(Color priColor) {
|
||||
return ExpansionTile(
|
||||
textColor: priColor,
|
||||
title: Text(
|
||||
@@ -159,7 +162,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppColorPreview() {
|
||||
Widget _buildAppColorPreview(Color priColor) {
|
||||
return ExpansionTile(
|
||||
textColor: priColor,
|
||||
trailing: ClipOval(
|
||||
@@ -196,7 +199,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLaunchPage() {
|
||||
Widget _buildLaunchPage(Color priColor) {
|
||||
return ExpansionTile(
|
||||
textColor: priColor,
|
||||
title: Text(
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/numx.dart';
|
||||
import 'package:toolbox/core/extension/stringx.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/app/path_with_prefix.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/path.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/view/page/sftp/downloading.dart';
|
||||
import 'package:toolbox/view/widget/fade_in.dart';
|
||||
|
||||
import '../../../core/extension/numx.dart';
|
||||
import '../../../core/extension/stringx.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/app/path_with_prefix.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../data/res/path.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../widget/fade_in.dart';
|
||||
import 'downloading.dart';
|
||||
|
||||
class SFTPDownloadedPage extends StatefulWidget {
|
||||
const SFTPDownloadedPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/numx.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/sftp/download_status.dart';
|
||||
import 'package:toolbox/data/provider/sftp_download.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/view/widget/center_loading.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../../core/extension/numx.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/sftp/download_status.dart';
|
||||
import '../../../data/provider/sftp_download.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../widget/center_loading.dart';
|
||||
import '../../widget/round_rect_card.dart';
|
||||
|
||||
class SFTPDownloadingPage extends StatefulWidget {
|
||||
const SFTPDownloadingPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import '../../../core/extension/numx.dart';
|
||||
import '../../../core/extension/stringx.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/server.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
import '../../../data/model/sftp/absolute_path.dart';
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'package:after_layout/after_layout.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/snippet.dart';
|
||||
import 'package:toolbox/data/provider/snippet.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/server/snippet.dart';
|
||||
import '../../../data/provider/snippet.dart';
|
||||
import '../../../data/res/font_style.dart';
|
||||
import '../../../generated/l10n.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/input_decoration.dart';
|
||||
|
||||
class SnippetEditPage extends StatefulWidget {
|
||||
const SnippetEditPage({Key? key, this.snippet}) : super(key: key);
|
||||
|
||||
@@ -5,16 +5,16 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:xterm/xterm.dart';
|
||||
|
||||
import '../../core/utils.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../core/utils/server.dart';
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
import '../../data/model/ssh/virtual_key.dart';
|
||||
import '../../data/provider/virtual_keyboard.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/terminal_theme.dart';
|
||||
import '../../data/res/virtual_key.dart';
|
||||
import '../../data/store/private_key.dart';
|
||||
import '../../locator.dart';
|
||||
|
||||
class SSHPage extends StatefulWidget {
|
||||
@@ -156,13 +156,15 @@ class _SSHPageState extends State<SSHPage> {
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
size: 17,
|
||||
)
|
||||
: Text(
|
||||
item.text,
|
||||
style: TextStyle(
|
||||
color: selected ? primaryColor : null,
|
||||
fontSize: 15,
|
||||
),
|
||||
);
|
||||
: PrimaryColor(builder: (context, color) {
|
||||
return Text(
|
||||
item.text,
|
||||
style: TextStyle(
|
||||
color: selected ? color : Colors.black,
|
||||
fontSize: 17,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
@@ -201,20 +203,3 @@ class _SSHPageState extends State<SSHPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<SSHClient> genClient(ServerPrivateInfo spi) async {
|
||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||
if (spi.pubKeyId == null) {
|
||||
return SSHClient(
|
||||
socket,
|
||||
username: spi.user,
|
||||
onPasswordRequest: () => spi.pwd,
|
||||
);
|
||||
}
|
||||
final key = locator<PrivateKeyStore>().get(spi.pubKeyId!);
|
||||
return SSHClient(
|
||||
socket,
|
||||
username: spi.user,
|
||||
identities: await compute(loadIndentity, key.privateKey),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,12 @@ class DropdownBtnItem {
|
||||
|
||||
Widget build(S s) => Row(
|
||||
children: [
|
||||
Icon(icon, color: primaryColor),
|
||||
PrimaryColor(builder: (context, primaryColor) {
|
||||
return Icon(
|
||||
icon,
|
||||
color: primaryColor,
|
||||
);
|
||||
}),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
|
||||
@@ -4,11 +4,14 @@ import 'package:toolbox/data/res/color.dart';
|
||||
InputDecoration buildDecoration(String label,
|
||||
{TextStyle? textStyle, IconData? icon, String? hint}) {
|
||||
return InputDecoration(
|
||||
labelText: label,
|
||||
labelStyle: textStyle,
|
||||
hintText: hint,
|
||||
icon: Icon(
|
||||
labelText: label,
|
||||
labelStyle: textStyle,
|
||||
hintText: hint,
|
||||
icon: PrimaryColor(builder: (context, primaryColor) {
|
||||
return Icon(
|
||||
icon,
|
||||
color: primaryColor,
|
||||
));
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/utils.dart';
|
||||
|
||||
import '../../core/utils/ui.dart';
|
||||
|
||||
const regUrl =
|
||||
r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]*";
|
||||
|
||||
@@ -730,10 +730,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: r_upgrade
|
||||
sha256: "5a597989ca065a47d62a992b23de068a118f1616a49bfa2518d552466c4ddc7b"
|
||||
sha256: be460ed1d2bf3b444a731aa2eeb38751faaef91097fed4bf9d138d3214b98999
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.1"
|
||||
version: "0.3.8+2"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@@ -47,7 +47,7 @@ dependencies:
|
||||
url: https://github.com/lollipopkit/circle_chart
|
||||
ref: main
|
||||
# path: ../circle_chart
|
||||
r_upgrade: ^0.4.1
|
||||
r_upgrade: ^0.3.6
|
||||
path_provider: ^2.0.9
|
||||
easy_isolate: ^1.3.0
|
||||
share_plus: ^6.3.0
|
||||
|
||||
Reference in New Issue
Block a user