fix & opt

fix: android in-app upgrade
fmt: proj struct
opt: fetch primaryColor
This commit is contained in:
lollipopkit
2023-02-01 12:52:40 +08:00
parent 068089d207
commit 4d741ac82a
30 changed files with 523 additions and 448 deletions

View File

@@ -1,13 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:toolbox/core/extension/colorx.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/res/build_data.dart';
import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/generated/l10n.dart'; import 'package:toolbox/generated/l10n.dart';
import 'package:toolbox/locator.dart'; import 'package:toolbox/locator.dart';
import 'package:toolbox/view/page/home.dart'; import 'package:toolbox/view/page/home.dart';
import 'core/utils/ui.dart';
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key); const MyApp({Key? key}) : super(key: key);

View File

@@ -11,7 +11,7 @@ import '../data/res/build_data.dart';
import '../data/service/app.dart'; import '../data/service/app.dart';
import '../generated/l10n.dart'; import '../generated/l10n.dart';
import '../locator.dart'; import '../locator.dart';
import 'utils.dart'; import 'utils/ui.dart';
final _logger = Logger('UPDATE'); 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 { Future<void> _doUpdate(AppUpdate update, BuildContext context, S s) async {
if (Platform.isAndroid) { if (Platform.isAndroid) {
await RUpgrade.upgrade(update.android, await RUpgrade.upgrade(update.android,
fileName: update.android.split('/').last); fileName: update.android.split('/').last, isAutoRequestInstall: true);
} else if (Platform.isIOS) { } else if (Platform.isIOS) {
await RUpgrade.upgradeFromAppStore('1586449703'); await RUpgrade.upgradeFromAppStore('1586449703');
} else { } else {

23
lib/core/utils/misc.dart Normal file
View 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;
}

View 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),
);
}

View File

@@ -1,22 +1,13 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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:toolbox/core/extension/stringx.dart';
import 'package:url_launcher/url_launcher.dart';
/// Must put this func out of any Class. import '../../generated/l10n.dart';
/// Because of this function is called by [compute] in [ServerProvider.genClient]. import '../../view/widget/card_dialog.dart';
/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure import '../persistant_store.dart';
List<SSHKeyPair> loadIndentity(String key) {
return SSHKeyPair.fromPem(key);
}
bool isDarkMode(BuildContext context) => bool isDarkMode(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark; 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( Widget buildPopuopMenu(
{required List<PopupMenuEntry> items, {required List<PopupMenuEntry> items,
required Function(dynamic) onSelected}) { 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 '';
}
}

View File

@@ -1,12 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import '../../core/extension/uint8list.dart'; import '../../core/extension/uint8list.dart';
import '../../core/provider_base.dart'; import '../../core/provider_base.dart';
import '../../core/utils.dart'; import '../../core/utils/server.dart';
import '../../locator.dart'; import '../../locator.dart';
import '../model/server/cpu_status.dart'; import '../model/server/cpu_status.dart';
import '../model/server/disk_info.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/server_private_info.dart';
import '../model/server/snippet.dart'; import '../model/server/snippet.dart';
import '../model/server/tcp_status.dart'; import '../model/server/tcp_status.dart';
import '../res/server_cmd.dart';
import '../res/status.dart'; import '../res/status.dart';
import '../store/private_key.dart';
import '../store/server.dart'; import '../store/server.dart';
import '../store/setting.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 { class ServerProvider extends BusyProvider {
List<Server> _servers = []; List<Server> _servers = [];
List<Server> get servers => _servers; List<Server> get servers => _servers;
@@ -54,18 +40,6 @@ class ServerProvider extends BusyProvider {
return Server(spi, initStatus, null, ServerConnectionState.disconnected); 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 { Future<void> refreshData({ServerPrivateInfo? spi}) async {
if (spi != null) { if (spi != null) {
_getData(spi); _getData(spi);

View File

@@ -2,9 +2,9 @@
class BuildData { class BuildData {
static const String name = "ServerBox"; static const String name = "ServerBox";
static const int build = 201; static const int build = 202;
static const String engine = 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"; "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-01-31 17:36:05.286138"; static const String buildAt = "2023-02-01 10:55:03.386055";
static const int modifications = 5; static const int modifications = 5;
} }

View File

@@ -1,9 +1,24 @@
import 'package:flutter/material.dart'; 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 { class DynamicColor {
/// 白天模式显示的颜色 /// 白天模式显示的颜色

View 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';

View File

@@ -4,17 +4,18 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:toolbox/core/extension/colorx.dart';
import 'package:toolbox/core/utils.dart'; import '../../core/extension/colorx.dart';
import 'package:toolbox/data/model/app/backup.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/data/res/color.dart'; import '../../data/model/app/backup.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../data/res/color.dart';
import 'package:toolbox/data/store/private_key.dart'; import '../../data/res/font_style.dart';
import 'package:toolbox/data/store/server.dart'; import '../../data/store/private_key.dart';
import 'package:toolbox/data/store/setting.dart'; import '../../data/store/server.dart';
import 'package:toolbox/data/store/snippet.dart'; import '../../data/store/setting.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../data/store/snippet.dart';
import 'package:toolbox/locator.dart'; import '../../generated/l10n.dart';
import '../../locator.dart';
const backupFormatVersion = 1; const backupFormatVersion = 1;
@@ -67,29 +68,32 @@ class BackupPage extends StatelessWidget {
Widget _buildCard(String text, IconData icon, MediaQueryData media, Widget _buildCard(String text, IconData icon, MediaQueryData media,
FutureOr Function() onTap) { FutureOr Function() onTap) {
final priColor = primaryColor; return PrimaryColor(
final textColor = priColor.isBrightColor ? Colors.black : Colors.white; builder: ((context, pColor) {
return GestureDetector( final textColor = pColor.isBrightColor ? Colors.black : Colors.white;
onTap: onTap, return GestureDetector(
child: Container( onTap: onTap,
decoration: BoxDecoration( child: Container(
borderRadius: BorderRadius.circular(37), color: priColor), decoration: BoxDecoration(
child: Padding( borderRadius: BorderRadius.circular(37), color: pColor),
padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), child: Padding(
child: Row( padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
mainAxisSize: MainAxisSize.min, child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min,
children: [ mainAxisAlignment: MainAxisAlignment.center,
Icon( children: [
icon, Icon(
color: textColor, icon,
color: textColor,
),
const SizedBox(width: 7),
Text(text, style: TextStyle(color: textColor)),
],
), ),
const SizedBox(width: 7), ),
Text(text, style: TextStyle(color: textColor)),
],
), ),
), );
), }),
); );
} }

View File

@@ -2,11 +2,12 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/res/color.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../data/res/color.dart';
import 'package:toolbox/view/widget/input_field.dart'; import '../../generated/l10n.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import '../widget/input_field.dart';
import '../widget/round_rect_card.dart';
class ConvertPage extends StatefulWidget { class ConvertPage extends StatefulWidget {
const ConvertPage({Key? key}) : super(key: key); const ConvertPage({Key? key}) : super(key: key);
@@ -104,75 +105,78 @@ class _ConvertPageState extends State<ConvertPage>
'URL $encode', 'URL $encode',
'URL $decode' 'URL $decode'
]; ];
return RoundRectCard( return PrimaryColor(builder: (context, primaryColor) {
ExpansionTile( return RoundRectCard(
tilePadding: const EdgeInsets.only(left: 7, right: 27), ExpansionTile(
childrenPadding: EdgeInsets.zero, tilePadding: const EdgeInsets.only(left: 7, right: 27),
title: Row( childrenPadding: EdgeInsets.zero,
children: [ title: Row(
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,
children: [ children: [
Text( TextButton(
typeOption[_typeOptionIndex], style: ButtonStyle(
textScaleFactor: 1.0, foregroundColor: MaterialStateProperty.all(primaryColor)),
textAlign: TextAlign.left, child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown),
style: TextStyle( onPressed: () {
fontSize: 16.0, final temp = _textEditingController.text;
fontWeight: FontWeight.w500, _textEditingController.text =
color: primaryColor), _textEditingControllerResult.text;
_textEditingControllerResult.text = temp;
},
), ),
Text( TextButton(
_s.currentMode, style: ButtonStyle(
textScaleFactor: 1.0, foregroundColor: MaterialStateProperty.all(primaryColor),
textAlign: TextAlign.right, ),
style: const TextStyle(fontSize: 9.0, color: Colors.grey), child: Icon(Icons.copy, semanticLabel: _s.copy),
onPressed: () => Clipboard.setData(
ClipboardData(
text: _textEditingControllerResult.text == ''
? ' '
: _textEditingControllerResult.text),
),
) )
], ],
), ),
), trailing: ConstrainedBox(
children: typeOption constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
.map( child: Column(
(e) => ListTile( crossAxisAlignment: CrossAxisAlignment.start,
title: Text( mainAxisAlignment: MainAxisAlignment.center,
e, children: [
Text(
typeOption[_typeOptionIndex],
textScaleFactor: 1.0,
textAlign: TextAlign.left,
style: TextStyle( style: TextStyle(
color: _theme.textTheme.bodyMedium?.color?.withAlpha(177), fontSize: 16.0,
), fontWeight: FontWeight.w500,
color: primaryColor),
), ),
trailing: _buildRadio(typeOption.indexOf(e)), Text(
), _s.currentMode,
) textScaleFactor: 1.0,
.toList(), 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() { Widget _buildResult() {

View File

@@ -1,23 +1,23 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/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/dropdown_menu.dart';
import '../widget/round_rect_card.dart';
import '../widget/two_line_text.dart';
import '../widget/url_text.dart';
class DockerManagePage extends StatefulWidget { class DockerManagePage extends StatefulWidget {
final ServerPrivateInfo spi; final ServerPrivateInfo spi;

View File

@@ -2,31 +2,31 @@ import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:toolbox/core/analysis.dart';
import 'package:toolbox/core/route.dart'; import '../../core/analysis.dart';
import 'package:toolbox/core/update.dart'; import '../../core/route.dart';
import 'package:toolbox/core/utils.dart'; import '../../core/update.dart';
import 'package:toolbox/data/model/app/navigation_item.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/data/provider/server.dart'; import '../../data/model/app/navigation_item.dart';
import 'package:toolbox/data/res/build_data.dart'; import '../../data/provider/server.dart';
import 'package:toolbox/data/res/color.dart'; import '../../data/res/build_data.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../data/res/font_style.dart';
import 'package:toolbox/data/res/icon.dart'; import '../../data/res/icon.dart';
import 'package:toolbox/data/res/tab.dart'; import '../../data/res/tab.dart';
import 'package:toolbox/data/res/url.dart'; import '../../data/res/url.dart';
import 'package:toolbox/data/store/setting.dart'; import '../../data/store/setting.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../generated/l10n.dart';
import 'package:toolbox/locator.dart'; import '../../locator.dart';
import 'package:toolbox/view/page/backup.dart'; import '../widget/url_text.dart';
import 'package:toolbox/view/page/convert.dart'; import 'backup.dart';
import 'package:toolbox/view/page/debug.dart'; import 'convert.dart';
import 'package:toolbox/view/page/ping.dart'; import 'debug.dart';
import 'package:toolbox/view/page/private_key/list.dart'; import 'ping.dart';
import 'package:toolbox/view/page/server/tab.dart'; import 'private_key/list.dart';
import 'package:toolbox/view/page/setting.dart'; import 'server/tab.dart';
import 'package:toolbox/view/page/sftp/downloaded.dart'; import 'setting.dart';
import 'package:toolbox/view/page/snippet/list.dart'; import 'sftp/downloaded.dart';
import 'package:toolbox/view/widget/url_text.dart'; import 'snippet/list.dart';
class MyHomePage extends StatefulWidget { class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.primaryColor}) : super(key: key); const MyHomePage({Key? key, required this.primaryColor}) : super(key: key);

View File

@@ -1,14 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/uint8list.dart';
import 'package:toolbox/core/utils.dart'; import '../../core/extension/uint8list.dart';
import 'package:toolbox/data/model/server/ping_result.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/data/provider/server.dart'; import '../../data/model/server/ping_result.dart';
import 'package:toolbox/data/res/color.dart'; import '../../data/provider/server.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../data/res/color.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../data/res/font_style.dart';
import 'package:toolbox/locator.dart'; import '../../generated/l10n.dart';
import 'package:toolbox/view/widget/input_field.dart'; import '../../locator.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import '../widget/input_field.dart';
import '../widget/round_rect_card.dart';
final doaminReg = final doaminReg =
RegExp(r'^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$'); 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) { Widget _buildResultItem(PingResult result) {
final unknown = s.unknown; final unknown = s.unknown;
final ms = s.ms; final ms = s.ms;
return RoundRectCard( return PrimaryColor(
ListTile( builder: ((context, primaryColor) {
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), return RoundRectCard(
title: Text( ListTile(
result.serverName, contentPadding:
style: TextStyle( const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
fontSize: 18, title: Text(
fontWeight: FontWeight.bold, result.serverName,
color: primaryColor, 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,
),
),
),
); );
} }

View File

@@ -1,17 +1,18 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/model/pkg/upgrade_info.dart'; import '../../data/model/pkg/upgrade_info.dart';
import 'package:toolbox/data/model/server/dist.dart'; import '../../data/model/server/dist.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/data/provider/pkg.dart'; import '../../data/model/server/server_private_info.dart';
import 'package:toolbox/data/provider/server.dart'; import '../../data/provider/pkg.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../data/provider/server.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../data/res/font_style.dart';
import 'package:toolbox/locator.dart'; import '../../generated/l10n.dart';
import 'package:toolbox/view/widget/center_loading.dart'; import '../../locator.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import '../widget/center_loading.dart';
import 'package:toolbox/view/widget/two_line_text.dart'; import '../widget/round_rect_card.dart';
import '../widget/two_line_text.dart';
class PkgManagePage extends StatefulWidget { class PkgManagePage extends StatefulWidget {
const PkgManagePage(this.spi, {Key? key}) : super(key: key); const PkgManagePage(this.spi, {Key? key}) : super(key: key);

View File

@@ -3,13 +3,14 @@ import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/model/server/private_key_info.dart'; import '../../../core/utils/ui.dart';
import 'package:toolbox/data/provider/private_key.dart'; import '../../../data/model/server/private_key_info.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../../data/provider/private_key.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../../data/res/font_style.dart';
import 'package:toolbox/locator.dart'; import '../../../generated/l10n.dart';
import 'package:toolbox/view/widget/input_decoration.dart'; import '../../../locator.dart';
import '../../widget/input_decoration.dart';
const _format = 'text/plain'; const _format = 'text/plain';

View File

@@ -29,7 +29,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
late MediaQueryData _media; late MediaQueryData _media;
late S _s; late S _s;
late Color pColor;
bool _showDistLogo = true; bool _showDistLogo = true;
@override @override
@@ -38,7 +37,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
_media = MediaQuery.of(context); _media = MediaQuery.of(context);
_s = S.of(context); _s = S.of(context);
_showDistLogo = locator<SettingStore>().showDistLogo.fetch()!; _showDistLogo = locator<SettingStore>().showDistLogo.fetch()!;
pColor = primaryColor;
} }
@override @override
@@ -175,12 +173,14 @@ class _ServerDetailPageState extends State<ServerDetailPage>
Widget _buildProgress(double percent) { Widget _buildProgress(double percent) {
if (percent > 100) percent = 100; if (percent > 100) percent = 100;
final percentWithinOne = percent / 100; final percentWithinOne = percent / 100;
return LinearProgressIndicator( return PrimaryColor(builder: (context, primaryColor) {
value: percentWithinOne, return LinearProgressIndicator(
minHeight: 7, value: percentWithinOne,
backgroundColor: progressColor.resolve(context), minHeight: 7,
color: pColor, backgroundColor: progressColor.resolve(context),
); color: primaryColor,
);
});
} }
Widget _buildUpTimeAndSys(ServerStatus ss) { Widget _buildUpTimeAndSys(ServerStatus ss) {

View File

@@ -1,19 +1,20 @@
import 'package:after_layout/after_layout.dart'; import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/route.dart';
import 'package:toolbox/core/utils.dart'; import '../../../core/route.dart';
import 'package:toolbox/data/model/server/private_key_info.dart'; import '../../../core/utils/ui.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import '../../../data/model/server/private_key_info.dart';
import 'package:toolbox/data/provider/private_key.dart'; import '../../../data/model/server/server_private_info.dart';
import 'package:toolbox/data/provider/server.dart'; import '../../../data/provider/private_key.dart';
import 'package:toolbox/data/res/color.dart'; import '../../../data/provider/server.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../../data/res/color.dart';
import 'package:toolbox/data/store/private_key.dart'; import '../../../data/res/font_style.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../../data/store/private_key.dart';
import 'package:toolbox/locator.dart'; import '../../../generated/l10n.dart';
import 'package:toolbox/view/page/private_key/edit.dart'; import '../../../locator.dart';
import 'package:toolbox/view/widget/input_decoration.dart'; import '../../widget/input_decoration.dart';
import '../private_key/edit.dart';
class ServerEditPage extends StatefulWidget { class ServerEditPage extends StatefulWidget {
const ServerEditPage({Key? key, this.spi}) : super(key: key); const ServerEditPage({Key? key, this.spi}) : super(key: key);
@@ -104,8 +105,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
focusNode: _nameFocus, focusNode: _nameFocus,
onSubmitted: (_) => _focusScope.requestFocus(_ipFocus), onSubmitted: (_) => _focusScope.requestFocus(_ipFocus),
decoration: buildDecoration(_s.name, decoration: buildDecoration(
icon: Icons.info, hint: _s.exampleName), _s.name,
icon: Icons.info,
hint: _s.exampleName,
),
), ),
TextField( TextField(
controller: _ipController, controller: _ipController,
@@ -114,16 +118,22 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
focusNode: _ipFocus, focusNode: _ipFocus,
autocorrect: false, autocorrect: false,
enableSuggestions: false, enableSuggestions: false,
decoration: buildDecoration(_s.host, decoration: buildDecoration(
icon: Icons.storage, hint: 'example.com'), _s.host,
icon: Icons.storage,
hint: 'example.com',
),
), ),
TextField( TextField(
controller: _portController, controller: _portController,
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
focusNode: _portFocus, focusNode: _portFocus,
onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus), onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus),
decoration: buildDecoration(_s.port, decoration: buildDecoration(
icon: Icons.format_list_numbered, hint: '22'), _s.port,
icon: Icons.format_list_numbered,
hint: '22',
),
), ),
TextField( TextField(
controller: _usernameController, controller: _usernameController,
@@ -131,16 +141,20 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
focusNode: _usernameFocus, focusNode: _usernameFocus,
autocorrect: false, autocorrect: false,
enableSuggestions: false, enableSuggestions: false,
decoration: buildDecoration(_s.user, decoration: buildDecoration(
icon: Icons.account_box, hint: 'root'), _s.user,
icon: Icons.account_box,
hint: 'root',
),
), ),
const SizedBox(height: 7), const SizedBox(height: 7),
Row( Row(
children: [ children: [
Text(_s.keyAuth), Text(_s.keyAuth),
Switch( Switch(
value: usePublicKey, value: usePublicKey,
onChanged: (val) => setState(() => usePublicKey = val)), onChanged: (val) => setState(() => usePublicKey = val),
),
], ],
), ),
!usePublicKey !usePublicKey
@@ -148,8 +162,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
controller: _passwordController, controller: _passwordController,
obscureText: true, obscureText: true,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
decoration: buildDecoration(_s.pwd, decoration: buildDecoration(
icon: Icons.password, hint: _s.pwd), _s.pwd,
icon: Icons.password,
hint: _s.pwd,
),
onSubmitted: (_) => {}, onSubmitted: (_) => {},
) )
: const SizedBox(), : const SizedBox(),
@@ -164,9 +181,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
final tiles = key.infos final tiles = key.infos
.map( .map(
(e) => ListTile( (e) => ListTile(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
title: Text(e.id, textAlign: TextAlign.start), title: Text(e.id, textAlign: TextAlign.start),
trailing: _buildRadio(key.infos.indexOf(e), e)), trailing: _buildRadio(key.infos.indexOf(e), e),
),
) )
.toList(); .toList();
tiles.add( tiles.add(
@@ -176,23 +194,25 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
trailing: IconButton( trailing: IconButton(
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
onPressed: () => AppRoute( onPressed: () => AppRoute(
const PrivateKeyEditPage(), const PrivateKeyEditPage(),
'private key edit page') 'private key edit page',
.go(context), ).go(context),
), ),
), ),
); );
return ExpansionTile( return PrimaryColor(builder: ((context, primaryColor) {
textColor: primaryColor, return ExpansionTile(
iconColor: primaryColor, textColor: primaryColor,
tilePadding: EdgeInsets.zero, iconColor: primaryColor,
childrenPadding: EdgeInsets.zero, tilePadding: EdgeInsets.zero,
title: Text( childrenPadding: EdgeInsets.zero,
_s.choosePrivateKey, title: Text(
style: const TextStyle(fontSize: 14), _s.choosePrivateKey,
), style: const TextStyle(fontSize: 14),
children: tiles, ),
); children: tiles,
);
}));
}, },
) )
: const SizedBox() : const SizedBox()

View File

@@ -3,32 +3,32 @@ import 'package:circle_chart/circle_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:provider/provider.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/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/dropdown_menu.dart';
import '../../widget/picker.dart';
import '../../widget/round_rect_card.dart';
import '../../widget/url_text.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 { class ServerPage extends StatefulWidget {
const ServerPage({Key? key}) : super(key: key); const ServerPage({Key? key}) : super(key: key);
@@ -41,7 +41,6 @@ class _ServerPageState extends State<ServerPage>
with AutomaticKeepAliveClientMixin, AfterLayoutMixin { with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
late MediaQueryData _media; late MediaQueryData _media;
late ThemeData _theme; late ThemeData _theme;
late Color _primaryColor;
late ServerProvider _serverProvider; late ServerProvider _serverProvider;
late SettingStore _settingStore; late SettingStore _settingStore;
late S _s; late S _s;
@@ -58,7 +57,6 @@ class _ServerPageState extends State<ServerPage>
super.didChangeDependencies(); super.didChangeDependencies();
_media = MediaQuery.of(context); _media = MediaQuery.of(context);
_theme = Theme.of(context); _theme = Theme.of(context);
_primaryColor = primaryColor;
_s = S.of(context); _s = S.of(context);
} }
@@ -94,9 +92,10 @@ class _ServerPageState extends State<ServerPage>
return Scaffold( return Scaffold(
body: child, body: child,
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () => onPressed: () => AppRoute(
AppRoute(const ServerEditPage(), 'Add server info page') const ServerEditPage(),
.go(context), 'Add server info page',
).go(context),
tooltip: _s.addAServer, tooltip: _s.addAServer,
heroTag: 'server page fab', heroTag: 'server page fab',
child: const Icon(Icons.add), child: const Icon(Icons.add),
@@ -353,12 +352,16 @@ class _ServerPageState extends State<ServerPage>
child: Stack( child: Stack(
children: [ children: [
Center( Center(
child: CircleChart( child: PrimaryColor(
progressColor: _primaryColor, builder: (context, primaryColor) {
progressNumber: percent, return CircleChart(
maxNumber: 100, progressColor: primaryColor,
width: 53, progressNumber: percent,
height: 53, maxNumber: 100,
width: 53,
height: 53,
);
},
), ),
), ),
Positioned.fill( Positioned.fill(
@@ -404,8 +407,10 @@ class _ServerPageState extends State<ServerPage>
showRoundDialog( showRoundDialog(
context, context,
_s.choose, _s.choose,
buildPicker(provider.snippets.map((e) => Text(e.name)).toList(), buildPicker(
(idx) => snippet = provider.snippets[idx]), provider.snippets.map((e) => Text(e.name)).toList(),
(idx) => snippet = provider.snippets[idx],
),
[ [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
@@ -418,8 +423,9 @@ class _ServerPageState extends State<ServerPage>
Text(result ?? _s.error, style: textSize13), Text(result ?? _s.error, style: textSize13),
[ [
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
child: Text(_s.ok)) child: Text(_s.ok),
)
], ],
); );
}, },

View File

@@ -1,18 +1,19 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/update.dart';
import 'package:toolbox/core/utils.dart'; import '../../core/update.dart';
import 'package:toolbox/data/provider/app.dart'; import '../../core/utils/ui.dart';
import 'package:toolbox/data/provider/server.dart'; import '../../data/provider/app.dart';
import 'package:toolbox/data/res/build_data.dart'; import '../../data/provider/server.dart';
import 'package:toolbox/data/res/color.dart'; import '../../data/res/build_data.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../data/res/color.dart';
import 'package:toolbox/data/res/tab.dart'; import '../../data/res/font_style.dart';
import 'package:toolbox/data/store/setting.dart'; import '../../data/res/tab.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../data/store/setting.dart';
import 'package:toolbox/locator.dart'; import '../../generated/l10n.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import '../../locator.dart';
import '../widget/round_rect_card.dart';
class SettingPage extends StatefulWidget { class SettingPage extends StatefulWidget {
const SettingPage({Key? key}) : super(key: key); const SettingPage({Key? key}) : super(key: key);
@@ -25,7 +26,6 @@ class _SettingPageState extends State<SettingPage> {
late final SettingStore _setting; late final SettingStore _setting;
late int _selectedColorValue; late int _selectedColorValue;
late int _launchPageIdx; late int _launchPageIdx;
late Color priColor;
late final ServerProvider _serverProvider; late final ServerProvider _serverProvider;
late MediaQueryData _media; late MediaQueryData _media;
late ThemeData _theme; late ThemeData _theme;
@@ -36,7 +36,6 @@ class _SettingPageState extends State<SettingPage> {
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
priColor = primaryColor;
_media = MediaQuery.of(context); _media = MediaQuery.of(context);
_theme = Theme.of(context); _theme = Theme.of(context);
_s = S.of(context); _s = S.of(context);
@@ -57,15 +56,19 @@ class _SettingPageState extends State<SettingPage> {
appBar: AppBar( appBar: AppBar(
title: Text(_s.setting), title: Text(_s.setting),
), ),
body: ListView( body: PrimaryColor(
padding: const EdgeInsets.all(17), builder: (context, primaryColor) {
children: [ return ListView(
_buildAppColorPreview(), padding: const EdgeInsets.all(17),
_buildUpdateInterval(), children: [
_buildCheckUpdate(), _buildAppColorPreview(primaryColor),
_buildLaunchPage(), _buildUpdateInterval(primaryColor),
_buildDistLogoSwitch(), _buildCheckUpdate(),
].map((e) => RoundRectCard(e)).toList(), _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( return ExpansionTile(
textColor: priColor, textColor: priColor,
title: Text( title: Text(
@@ -159,7 +162,7 @@ class _SettingPageState extends State<SettingPage> {
); );
} }
Widget _buildAppColorPreview() { Widget _buildAppColorPreview(Color priColor) {
return ExpansionTile( return ExpansionTile(
textColor: priColor, textColor: priColor,
trailing: ClipOval( trailing: ClipOval(
@@ -196,7 +199,7 @@ class _SettingPageState extends State<SettingPage> {
); );
} }
Widget _buildLaunchPage() { Widget _buildLaunchPage(Color priColor) {
return ExpansionTile( return ExpansionTile(
textColor: priColor, textColor: priColor,
title: Text( title: Text(

View File

@@ -1,16 +1,18 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/numx.dart';
import 'package:toolbox/core/extension/stringx.dart'; import '../../../core/extension/numx.dart';
import 'package:toolbox/core/route.dart'; import '../../../core/extension/stringx.dart';
import 'package:toolbox/core/utils.dart'; import '../../../core/route.dart';
import 'package:toolbox/data/model/app/path_with_prefix.dart'; import '../../../core/utils/misc.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../../core/utils/ui.dart';
import 'package:toolbox/data/res/path.dart'; import '../../../data/model/app/path_with_prefix.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../../data/res/font_style.dart';
import 'package:toolbox/view/page/sftp/downloading.dart'; import '../../../data/res/path.dart';
import 'package:toolbox/view/widget/fade_in.dart'; import '../../../generated/l10n.dart';
import '../../widget/fade_in.dart';
import 'downloading.dart';
class SFTPDownloadedPage extends StatefulWidget { class SFTPDownloadedPage extends StatefulWidget {
const SFTPDownloadedPage({Key? key}) : super(key: key); const SFTPDownloadedPage({Key? key}) : super(key: key);

View File

@@ -1,13 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/numx.dart';
import 'package:toolbox/core/utils.dart'; import '../../../core/extension/numx.dart';
import 'package:toolbox/data/model/sftp/download_status.dart'; import '../../../core/utils/misc.dart';
import 'package:toolbox/data/provider/sftp_download.dart'; import '../../../core/utils/ui.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../../data/model/sftp/download_status.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../../data/provider/sftp_download.dart';
import 'package:toolbox/view/widget/center_loading.dart'; import '../../../data/res/font_style.dart';
import 'package:toolbox/view/widget/round_rect_card.dart'; import '../../../generated/l10n.dart';
import '../../widget/center_loading.dart';
import '../../widget/round_rect_card.dart';
class SFTPDownloadingPage extends StatefulWidget { class SFTPDownloadingPage extends StatefulWidget {
const SFTPDownloadingPage({Key? key}) : super(key: key); const SFTPDownloadingPage({Key? key}) : super(key: key);

View File

@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
import '../../../core/extension/numx.dart'; import '../../../core/extension/numx.dart';
import '../../../core/extension/stringx.dart'; import '../../../core/extension/stringx.dart';
import '../../../core/route.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.dart';
import '../../../data/model/server/server_private_info.dart'; import '../../../data/model/server/server_private_info.dart';
import '../../../data/model/sftp/absolute_path.dart'; import '../../../data/model/sftp/absolute_path.dart';

View File

@@ -1,12 +1,13 @@
import 'package:after_layout/after_layout.dart'; import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:toolbox/core/utils.dart';
import 'package:toolbox/data/model/server/snippet.dart'; import '../../../core/utils/ui.dart';
import 'package:toolbox/data/provider/snippet.dart'; import '../../../data/model/server/snippet.dart';
import 'package:toolbox/data/res/font_style.dart'; import '../../../data/provider/snippet.dart';
import 'package:toolbox/generated/l10n.dart'; import '../../../data/res/font_style.dart';
import 'package:toolbox/locator.dart'; import '../../../generated/l10n.dart';
import 'package:toolbox/view/widget/input_decoration.dart'; import '../../../locator.dart';
import '../../widget/input_decoration.dart';
class SnippetEditPage extends StatefulWidget { class SnippetEditPage extends StatefulWidget {
const SnippetEditPage({Key? key, this.snippet}) : super(key: key); const SnippetEditPage({Key? key, this.snippet}) : super(key: key);

View File

@@ -5,16 +5,16 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/data/res/color.dart';
import 'package:xterm/xterm.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/server/server_private_info.dart';
import '../../data/model/ssh/virtual_key.dart'; import '../../data/model/ssh/virtual_key.dart';
import '../../data/provider/virtual_keyboard.dart'; import '../../data/provider/virtual_keyboard.dart';
import '../../data/res/color.dart';
import '../../data/res/terminal_theme.dart'; import '../../data/res/terminal_theme.dart';
import '../../data/res/virtual_key.dart'; import '../../data/res/virtual_key.dart';
import '../../data/store/private_key.dart';
import '../../locator.dart'; import '../../locator.dart';
class SSHPage extends StatefulWidget { class SSHPage extends StatefulWidget {
@@ -156,13 +156,15 @@ class _SSHPageState extends State<SSHPage> {
color: isDark ? Colors.white : Colors.black, color: isDark ? Colors.white : Colors.black,
size: 17, size: 17,
) )
: Text( : PrimaryColor(builder: (context, color) {
item.text, return Text(
style: TextStyle( item.text,
color: selected ? primaryColor : null, style: TextStyle(
fontSize: 15, color: selected ? color : Colors.black,
), fontSize: 17,
); ),
);
});
return InkWell( return InkWell(
onTap: () { 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),
);
}

View File

@@ -14,7 +14,12 @@ class DropdownBtnItem {
Widget build(S s) => Row( Widget build(S s) => Row(
children: [ children: [
Icon(icon, color: primaryColor), PrimaryColor(builder: (context, primaryColor) {
return Icon(
icon,
color: primaryColor,
);
}),
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),

View File

@@ -4,11 +4,14 @@ import 'package:toolbox/data/res/color.dart';
InputDecoration buildDecoration(String label, InputDecoration buildDecoration(String label,
{TextStyle? textStyle, IconData? icon, String? hint}) { {TextStyle? textStyle, IconData? icon, String? hint}) {
return InputDecoration( return InputDecoration(
labelText: label, labelText: label,
labelStyle: textStyle, labelStyle: textStyle,
hintText: hint, hintText: hint,
icon: Icon( icon: PrimaryColor(builder: (context, primaryColor) {
return Icon(
icon, icon,
color: primaryColor, color: primaryColor,
)); );
}),
);
} }

View File

@@ -1,6 +1,7 @@
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:toolbox/core/utils.dart';
import '../../core/utils/ui.dart';
const regUrl = const regUrl =
r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]*"; r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]*";

View File

@@ -730,10 +730,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: r_upgrade name: r_upgrade
sha256: "5a597989ca065a47d62a992b23de068a118f1616a49bfa2518d552466c4ddc7b" sha256: be460ed1d2bf3b444a731aa2eeb38751faaef91097fed4bf9d138d3214b98999
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.4.1" version: "0.3.8+2"
share_plus: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -47,7 +47,7 @@ dependencies:
url: https://github.com/lollipopkit/circle_chart url: https://github.com/lollipopkit/circle_chart
ref: main ref: main
# path: ../circle_chart # path: ../circle_chart
r_upgrade: ^0.4.1 r_upgrade: ^0.3.6
path_provider: ^2.0.9 path_provider: ^2.0.9
easy_isolate: ^1.3.0 easy_isolate: ^1.3.0
share_plus: ^6.3.0 share_plus: ^6.3.0