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_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);

View File

@@ -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
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 '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 '';
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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 {
/// 白天模式显示的颜色

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

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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);

View File

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

View File

@@ -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);

View File

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

View File

@@ -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) {

View File

@@ -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()

View File

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

View File

@@ -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(

View File

@@ -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);

View File

@@ -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);

View File

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

View File

@@ -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);

View File

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

View File

@@ -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,
),

View File

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

View File

@@ -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+&@#/%=~_|]*";

View File

@@ -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:

View File

@@ -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