opt.: mem usage

This commit is contained in:
lollipopkit
2023-09-13 15:22:48 +08:00
parent 278d5984b2
commit eb158e63a2
44 changed files with 333 additions and 360 deletions

View File

@@ -472,7 +472,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -480,7 +480,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -604,7 +604,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -612,7 +612,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -630,7 +630,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -638,7 +638,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -659,7 +659,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -672,7 +672,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -698,7 +698,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -711,7 +711,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -734,7 +734,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -747,7 +747,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -3,12 +3,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/extension/context/common.dart';
import 'package:toolbox/core/extension/locale.dart';
import 'package:toolbox/data/res/store.dart';
import 'core/utils/ui.dart';
import 'data/res/build_data.dart';
import 'data/res/color.dart';
import 'data/store/setting.dart';
import 'locator.dart';
import 'view/page/full_screen.dart';
import 'view/page/home.dart';
@@ -21,15 +20,13 @@ const _drawerTheme = DrawerThemeData(
);
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
final _setting = locator<SettingStore>();
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
setTransparentNavigationBar(context);
final child = _wrapTheme(context);
if (_setting.useSystemPrimaryColor.fetch()) {
if (Stores.setting.useSystemPrimaryColor.fetch()) {
return _wrapSystemColor(context, child);
}
return child;
@@ -37,13 +34,13 @@ class MyApp extends StatelessWidget {
Widget _wrapTheme(BuildContext context) {
return ValueListenableBuilder<int>(
valueListenable: _setting.themeMode.listenable(),
valueListenable: Stores.setting.themeMode.listenable(),
builder: (_, tMode, __) {
final isAMOLED = tMode >= 0 && tMode <= ThemeMode.values.length - 1;
// Issue #57
// if not [ok] -> [AMOLED] mode, use [ThemeMode.dark]
final themeMode = isAMOLED ? ThemeMode.values[tMode] : ThemeMode.dark;
final locale = _setting.locale.fetch().toLocale;
final locale = Stores.setting.locale.fetch().toLocale;
final darkTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
@@ -63,7 +60,7 @@ class MyApp extends StatelessWidget {
colorSchemeSeed: primaryColor,
),
darkTheme: isAMOLED ? darkTheme : _getAmoledTheme(darkTheme),
home: _setting.fullScreen.fetch()
home: Stores.setting.fullScreen.fetch()
? const FullScreenPage()
: const HomePage(),
);

View File

@@ -3,10 +3,9 @@ import 'dart:async';
import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/foundation.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/res/store.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.
///
@@ -32,7 +31,7 @@ enum GenSSHClientStatus {
}
String getPrivateKey(String id) {
final pki = locator<PrivateKeyStore>().get(id);
final pki = Stores.key.get(id);
if (pki == null) {
throw SSHErr(
type: SSHErrType.noPrivateKey,

View File

@@ -6,12 +6,7 @@ import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/snippet.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/res/path.dart';
import 'package:toolbox/data/store/docker.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/locator.dart';
import 'package:toolbox/data/res/store.dart';
const backupFormatVersion = 1;
@@ -62,11 +57,11 @@ class Backup {
Backup.loadFromStore()
: version = backupFormatVersion,
date = DateTime.now().toString().split('.').first,
spis = _server.fetch(),
snippets = _snippet.fetch(),
keys = _privateKey.fetch(),
dockerHosts = _dockerHosts.fetchAll(),
settings = _setting.toJson();
spis = Stores.server.fetch(),
snippets = Stores.snippet.fetch(),
keys = Stores.key.fetch(),
dockerHosts = Stores.docker.fetchAll(),
settings = Stores.setting.toJson();
static Future<void> backup() async {
final result = _diyEncrtpt(json.encode(Backup.loadFromStore()));
@@ -75,18 +70,18 @@ class Backup {
Future<void> restore() async {
for (final s in snippets) {
_snippet.put(s);
Stores.snippet.put(s);
}
for (final s in spis) {
_server.put(s);
Stores.server.put(s);
}
for (final s in keys) {
_privateKey.put(s);
Stores.key.put(s);
}
for (final k in dockerHosts.keys) {
final val = dockerHosts[k];
if (val != null && val is String && val.isNotEmpty) {
_dockerHosts.put(k, val);
Stores.docker.put(k, val);
}
}
}
@@ -95,12 +90,6 @@ class Backup {
: this.fromJson(json.decode(_diyDecrypt(raw)));
}
final _server = locator<ServerStore>();
final _snippet = locator<SnippetStore>();
final _privateKey = locator<PrivateKeyStore>();
final _dockerHosts = locator<DockerStore>();
final _setting = locator<SettingStore>();
String _diyEncrtpt(String raw) => json.encode(
raw.codeUnits.map((e) => e * 2 + 1).toList(growable: false),
);

View File

@@ -109,8 +109,8 @@ Cpus parseBsdCpu(String raw) {
.allMatches(raw)
.map((e) => double.parse(e.group(1) ?? '0') * 100)
.toList();
if (percents.length != 3) return initCpuStatus;
return initCpuStatus
if (percents.length != 3) return InitStatus.cpus;
return InitStatus.cpus
..now = [
OneTimeCpuStatus('cpu', percents[0].toInt(), 0, 0,
percents[2].toInt() + percents[1].toInt(), 0, 0, 0)

View File

@@ -1,11 +1,10 @@
import '../../../locator.dart';
import '../../store/setting.dart';
import 'package:toolbox/data/res/store.dart';
class TryLimiter {
final Map<String, int> _triedTimes = {};
bool canTry(String id) {
final maxCount = locator<SettingStore>().maxRetryCount.fetch();
final maxCount = Stores.setting.maxRetryCount.fetch();
if (maxCount <= 0) {
return true;
}

View File

@@ -38,15 +38,9 @@ class DebugProvider extends ChangeNotifier {
}
void addMultiline(Object data, [Color color = Colors.blue]) {
final widget = Text(
'$data',
style: TextStyle(
color: color,
),
);
_addWidget(SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: widget,
child: Text('$data', style: TextStyle(color: color)),
));
}

View File

@@ -9,8 +9,7 @@ import 'package:toolbox/data/model/docker/image.dart';
import 'package:toolbox/data/model/docker/ps.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/store/docker.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/data/res/store.dart';
final _dockerNotFound = RegExp(r'command not found|Unknown command');
final _versionReg = RegExp(r'(Version:)\s+([0-9]+\.[0-9]+\.[0-9]+)');
@@ -19,8 +18,6 @@ final _editionReg = RegExp(r'Docker Engine - [a-zA-Z]+');
final _dockerPrefixReg = RegExp(r'(sudo )?docker ');
class DockerProvider extends ChangeNotifier {
final _dockerStore = locator<DockerStore>();
SSHClient? client;
String? userName;
List<DockerPsItem>? items;
@@ -177,7 +174,7 @@ class DockerProvider extends ChangeNotifier {
// judge whether to use DOCKER_HOST
String _wrap(String cmd) {
final dockerHost = _dockerStore.fetch(hostId!);
final dockerHost = Stores.docker.fetch(hostId!);
if (dockerHost == null || dockerHost.isEmpty) {
return cmd.withLangExport;
}

View File

@@ -1,26 +1,24 @@
import 'package:flutter/material.dart';
import 'package:toolbox/data/model/server/private_key_info.dart';
import 'package:toolbox/data/store/private_key.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/data/res/store.dart';
class PrivateKeyProvider extends ChangeNotifier {
List<PrivateKeyInfo> get pkis => _pkis;
final _store = locator<PrivateKeyStore>();
late List<PrivateKeyInfo> _pkis;
void loadData() {
_pkis = _store.fetch();
_pkis = Stores.key.fetch();
}
void add(PrivateKeyInfo info) {
_pkis.add(info);
_store.put(info);
Stores.key.put(info);
notifyListeners();
}
void delete(PrivateKeyInfo info) {
_pkis.removeWhere((e) => e.id == info.id);
_store.delete(info);
Stores.key.delete(info);
notifyListeners();
}
@@ -31,7 +29,7 @@ class PrivateKeyProvider extends ChangeNotifier {
} else {
_pkis[idx] = newInfo;
}
_store.put(newInfo);
Stores.key.put(newInfo);
notifyListeners();
}
}

View File

@@ -4,19 +4,17 @@ import 'package:flutter/foundation.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/res/store.dart';
import '../../core/extension/order.dart';
import '../../core/extension/uint8list.dart';
import '../../core/utils/server.dart';
import '../../locator.dart';
import '../model/server/server.dart';
import '../model/server/server_private_info.dart';
import '../model/server/server_status_update_req.dart';
import '../model/server/snippet.dart';
import '../model/server/try_limiter.dart';
import '../res/status.dart';
import '../store/server.dart';
import '../store/setting.dart';
typedef ServersMap = Map<String, Server>;
@@ -32,20 +30,17 @@ class ServerProvider extends ChangeNotifier {
Timer? _timer;
final _serverStore = locator<ServerStore>();
final _settingStore = locator<SettingStore>();
Future<void> loadLocalData() async {
// Issue #147
// Clear all servers because of restarting app will cause duplicate servers
_servers.clear();
_serverOrder.clear();
final spis = _serverStore.fetch();
final spis = Stores.server.fetch();
for (final spi in spis) {
_servers[spi.id] = genServer(spi);
}
final serverOrder_ = _settingStore.serverOrder.fetch();
final serverOrder_ = Stores.setting.serverOrder.fetch();
if (serverOrder_.isNotEmpty) {
spis.reorder(
order: serverOrder_,
@@ -57,7 +52,7 @@ class ServerProvider extends ChangeNotifier {
}
// Must use [equals] to compare [Order] here.
if (!_serverOrder.equals(serverOrder_)) {
_settingStore.serverOrder.put(_serverOrder);
Stores.setting.serverOrder.put(_serverOrder);
}
_updateTags();
notifyListeners();
@@ -85,13 +80,13 @@ class ServerProvider extends ChangeNotifier {
s.spi.tags![i] = new_;
}
}
_serverStore.update(s.spi, s.spi);
Stores.server.update(s.spi, s.spi);
}
_updateTags();
}
Server genServer(ServerPrivateInfo spi) {
return Server(spi, initStatus, null, ServerState.disconnected);
return Server(spi, InitStatus.status, null, ServerState.disconnected);
}
/// if [spi] is specificed then only refresh this server
@@ -115,7 +110,7 @@ class ServerProvider extends ChangeNotifier {
}
Future<void> startAutoRefresh() async {
final duration = _settingStore.serverStatusUpdateInterval.fetch();
final duration = Stores.setting.serverStatusUpdateInterval.fetch();
stopAutoRefresh();
if (duration == 0) return;
_timer = Timer.periodic(Duration(seconds: duration), (_) async {
@@ -158,9 +153,9 @@ class ServerProvider extends ChangeNotifier {
void addServer(ServerPrivateInfo spi) {
_servers[spi.id] = genServer(spi);
notifyListeners();
_serverStore.put(spi);
Stores.server.put(spi);
_serverOrder.add(spi.id);
_settingStore.serverOrder.put(_serverOrder);
Stores.setting.serverOrder.put(_serverOrder);
_updateTags();
refreshData(spi: spi);
}
@@ -168,19 +163,19 @@ class ServerProvider extends ChangeNotifier {
void delServer(String id) {
_servers.remove(id);
_serverOrder.remove(id);
_settingStore.serverOrder.put(_serverOrder);
Stores.setting.serverOrder.put(_serverOrder);
_updateTags();
notifyListeners();
_serverStore.delete(id);
Stores.server.delete(id);
}
void deleteAll() {
_servers.clear();
_serverOrder.clear();
_settingStore.serverOrder.put(_serverOrder);
Stores.setting.serverOrder.put(_serverOrder);
_updateTags();
notifyListeners();
_serverStore.deleteAll();
Stores.server.deleteAll();
}
Future<void> updateServer(
@@ -188,7 +183,7 @@ class ServerProvider extends ChangeNotifier {
ServerPrivateInfo newSpi,
) async {
if (old != newSpi) {
_serverStore.update(old, newSpi);
Stores.server.update(old, newSpi);
_servers[old.id]?.spi = newSpi;
if (newSpi.id != old.id) {
@@ -196,14 +191,14 @@ class ServerProvider extends ChangeNotifier {
_servers[newSpi.id]?.spi = newSpi;
_servers.remove(old.id);
_serverOrder.update(old.id, newSpi.id);
_settingStore.serverOrder.put(_serverOrder);
Stores.setting.serverOrder.put(_serverOrder);
}
// Only reconnect if neccessary
if (newSpi.shouldReconnect(old)) {
_servers[newSpi.id]?.client = await genClient(
newSpi,
timeout: _settingStore.timeoutD,
timeout: Stores.setting.timeoutD,
);
refreshData(spi: newSpi);
}
@@ -239,7 +234,7 @@ class ServerProvider extends ChangeNotifier {
try {
s.client = await genClient(
spi,
timeout: _settingStore.timeoutD,
timeout: Stores.setting.timeoutD,
);
} catch (e) {
_limiter.inc(sid);

View File

@@ -2,11 +2,9 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:toolbox/data/model/server/snippet.dart';
import 'package:toolbox/data/store/snippet.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/data/res/store.dart';
import '../../core/extension/order.dart';
import '../store/setting.dart';
class SnippetProvider extends ChangeNotifier {
late Order<Snippet> _snippets;
@@ -15,20 +13,17 @@ class SnippetProvider extends ChangeNotifier {
final _tags = <String>[];
List<String> get tags => _tags;
final _store = locator<SnippetStore>();
final _setting = locator<SettingStore>();
void loadData() {
_snippets = _store.fetch();
final order = _setting.snippetOrder.fetch();
_snippets = Stores.snippet.fetch();
final order = Stores.setting.snippetOrder.fetch();
if (order.isNotEmpty) {
final surplus = _snippets.reorder(
order: order,
finder: (n, name) => n.name == name,
);
order.removeWhere((e) => surplus.any((ele) => ele == e));
if (order != _setting.snippetOrder.fetch()) {
_setting.snippetOrder.put(order);
if (order != Stores.setting.snippetOrder.fetch()) {
Stores.setting.snippetOrder.put(order);
}
}
_addInternal();
@@ -36,12 +31,12 @@ class SnippetProvider extends ChangeNotifier {
}
void _addInternal() {
if (!_setting.fTISBM.fetch()) {
if (!Stores.setting.fTISBM.fetch()) {
return;
}
_snippets.add(installSBM);
_store.put(installSBM);
_setting.fTISBM.put(false);
Stores.snippet.put(installSBM);
Stores.setting.fTISBM.put(false);
}
void _updateTags() {
@@ -58,21 +53,21 @@ class SnippetProvider extends ChangeNotifier {
void add(Snippet snippet) {
_snippets.add(snippet);
_store.put(snippet);
Stores.snippet.put(snippet);
_updateTags();
notifyListeners();
}
void del(Snippet snippet) {
_snippets.remove(snippet);
_store.delete(snippet);
Stores.snippet.delete(snippet);
_updateTags();
notifyListeners();
}
void update(Snippet old, Snippet newOne) {
_store.delete(old);
_store.put(newOne);
Stores.snippet.delete(old);
Stores.snippet.put(newOne);
_snippets.remove(old);
_snippets.add(newOne);
_updateTags();
@@ -84,7 +79,7 @@ class SnippetProvider extends ChangeNotifier {
if (s.tags?.contains(old) ?? false) {
s.tags?.remove(old);
s.tags?.add(newOne);
_store.put(s);
Stores.snippet.put(s);
}
}
_updateTags();

View File

@@ -1,9 +1,7 @@
import 'package:flutter/widgets.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:xterm/core.dart';
import '../../locator.dart';
import '../store/setting.dart';
class VirtualKeyboard extends TerminalInputHandler with ChangeNotifier {
VirtualKeyboard();
@@ -25,8 +23,6 @@ class VirtualKeyboard extends TerminalInputHandler with ChangeNotifier {
}
}
final _setting = locator<SettingStore>();
void reset(TerminalKeyboardEvent e) {
if (e.ctrl) {
ctrl = false;
@@ -43,7 +39,7 @@ class VirtualKeyboard extends TerminalInputHandler with ChangeNotifier {
ctrl: event.ctrl || ctrl,
alt: event.alt || alt,
);
if (_setting.sshVirtualKeyAutoOff.fetch()) {
if (Stores.setting.sshVirtualKeyAutoOff.fetch()) {
reset(e);
}
return defaultInputHandler.call(e);

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 547;
static const int build = 550;
static const String engine = "3.13.2";
static const String buildAt = "2023-09-12 14:04:07.018274";
static const int modifications = 4;
static const int script = 14;
static const String buildAt = "2023-09-13 15:19:48";
static const int modifications = 45;
static const int script = 15;
}

View File

@@ -5,6 +5,8 @@ import '../model/app/dynamic_color.dart';
late Color primaryColor;
class DynamicColors {
const DynamicColors._();
static const content = DynamicColor(Colors.black87, Colors.white70);
static const bg = DynamicColor(Colors.white, Colors.black);
static const progress = DynamicColor(Colors.black12, Colors.white10);

View File

@@ -3,6 +3,8 @@ import 'dart:ui';
import 'package:toolbox/data/model/ssh/virtual_key.dart';
class Defaults {
const Defaults._();
// default server details page cards order
static const detailCardOrder = [
'uptime',

View File

@@ -1,6 +1,8 @@
import 'package:toolbox/data/model/app/github_id.dart';
class GithubIds {
const GithubIds._();
// Thanks
// If you want to change the url, please open an issue.
static const contributors = <GhId>{

View File

@@ -33,6 +33,8 @@ import 'package:highlight/languages/xml.dart';
import 'package:highlight/languages/yaml.dart';
class Highlights {
const Highlights._();
/// - KEY: fileNameSuffix
/// - VAL: highlight
static final all = {

View File

@@ -1,6 +1,8 @@
import 'package:logging/logging.dart';
class Loggers {
const Loggers._();
static final app = Logger('App');
static final parse = Logger('Parse');
}

View File

@@ -3,6 +3,8 @@ import 'dart:convert';
import 'package:flutter/services.dart';
class Miscs {
const Miscs._();
/// RegExp for number
static final numReg = RegExp(r'\s{1,}');

View File

@@ -4,6 +4,8 @@ import 'package:path_provider/path_provider.dart';
import 'package:toolbox/core/utils/platform.dart';
class Paths {
const Paths._();
static String? _docDir;
static String? _sftpDir;
static String? _fontDir;

View File

@@ -8,13 +8,10 @@ import '../model/server/server_status.dart';
import '../model/server/conn.dart';
import '../model/server/system.dart';
Memory get _initMemory => const Memory(
total: 1,
free: 1,
cache: 0,
avail: 1,
);
OneTimeCpuStatus get _initOneTimeCpuStatus => OneTimeCpuStatus(
class InitStatus {
const InitStatus._();
static OneTimeCpuStatus get _initOneTimeCpuStatus => OneTimeCpuStatus(
'cpu',
0,
0,
@@ -24,28 +21,28 @@ OneTimeCpuStatus get _initOneTimeCpuStatus => OneTimeCpuStatus(
0,
0,
);
Cpus get initCpuStatus => Cpus(
static Cpus get cpus => Cpus(
[_initOneTimeCpuStatus],
[_initOneTimeCpuStatus],
);
NetSpeedPart get _initNetSpeedPart => NetSpeedPart(
static NetSpeedPart get _initNetSpeedPart => NetSpeedPart(
'',
BigInt.zero,
BigInt.zero,
0,
);
NetSpeed get initNetSpeed => NetSpeed(
static NetSpeed get netSpeed => NetSpeed(
[_initNetSpeedPart],
[_initNetSpeedPart],
);
Swap get _initSwap => const Swap(
total: 0,
free: 0,
cached: 0,
);
ServerStatus get initStatus => ServerStatus(
cpu: initCpuStatus,
mem: _initMemory,
static ServerStatus get status => ServerStatus(
cpu: cpus,
mem: const Memory(
total: 1,
free: 1,
cache: 0,
avail: 1,
),
sysVer: 'Loading...',
uptime: '',
disk: [
@@ -59,8 +56,13 @@ ServerStatus get initStatus => ServerStatus(
)
],
tcp: const Conn(maxConn: 0, active: 0, passive: 0, fail: 0),
netSpeed: initNetSpeed,
swap: _initSwap,
netSpeed: netSpeed,
swap: const Swap(
total: 0,
free: 0,
cached: 0,
),
system: SystemType.linux,
temps: Temperatures(),
);
}

18
lib/data/res/store.dart Normal file
View File

@@ -0,0 +1,18 @@
import 'package:toolbox/data/store/docker.dart';
import 'package:toolbox/data/store/history.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/locator.dart';
class Stores {
const Stores._();
static final setting = locator<SettingStore>();
static final server = locator<ServerStore>();
static final docker = locator<DockerStore>();
static final history = locator<HistoryStore>();
static final key = locator<PrivateKeyStore>();
static final snippet = locator<SnippetStore>();
}

View File

@@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:xterm/ui.dart';
const termDarkTheme = TerminalTheme(
class TerminalThemes {
const TerminalThemes._();
static const dark = TerminalTheme(
cursor: Color.fromARGB(137, 174, 175, 173),
selection: Color.fromARGB(147, 174, 175, 173),
foreground: Color(0XFFCCCCCC),
@@ -26,8 +29,7 @@ const termDarkTheme = TerminalTheme(
brightWhite: Color.fromARGB(255, 233, 235, 235),
black: Colors.black,
);
const termLightTheme = TerminalTheme(
static const light = TerminalTheme(
cursor: Color.fromARGB(153, 174, 175, 173),
selection: Color.fromARGB(102, 174, 175, 173),
foreground: Color(0XFF000000),
@@ -52,3 +54,4 @@ const termLightTheme = TerminalTheme(
brightWhite: Color.fromARGB(255, 233, 235, 235),
black: Colors.black,
);
}

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
class UIs {
const UIs._();
/// Font style
static const textSize9Grey = TextStyle(color: Colors.grey, fontSize: 9);

View File

@@ -1,4 +1,6 @@
class Urls {
const Urls._();
static const resBase = 'https://res.lolli.tech/serverbox';
static const myGithub = 'https://github.com/lollipopkit';
static const appHelp = '$myGithub/flutter_server_box#-help';

View File

@@ -6,6 +6,7 @@ import 'package:logging/logging.dart';
import 'package:macos_window_utils/window_manipulator.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:toolbox/data/res/store.dart';
import 'app.dart';
import 'core/analysis.dart';
@@ -27,7 +28,6 @@ import 'data/provider/snippet.dart';
import 'data/provider/virtual_keyboard.dart';
import 'data/res/color.dart';
import 'data/res/misc.dart';
import 'data/store/setting.dart';
import 'locator.dart';
import 'view/widget/custom_appbar.dart';
import 'view/widget/rebuild.dart';
@@ -49,7 +49,7 @@ Future<void> main() async {
ChangeNotifierProvider(create: (_) => locator<PrivateKeyProvider>()),
ChangeNotifierProvider(create: (_) => locator<SftpProvider>()),
],
child: RebuildWidget(
child: const RebuildWidget(
child: MyApp(),
),
),
@@ -61,12 +61,6 @@ void _runInZone(void Function() body) {
final zoneSpec = ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
parent.print(zone, line);
// This is a hack to avoid
// `setState() or markNeedsBuild() called during build`
// error.
Future.delayed(const Duration(milliseconds: 1), () {
_debug?.addText(line);
});
},
);
@@ -90,16 +84,15 @@ Future<void> initApp() async {
_setupProviders();
// Load font
final settings = locator<SettingStore>();
loadFontFile(settings.fontPath.fetch());
primaryColor = Color(settings.primaryColor.fetch());
primaryColor = Color(Stores.setting.primaryColor.fetch());
loadFontFile(Stores.setting.fontPath.fetch());
// Don't call it via `await`, it will block the main thread.
if (settings.icloudSync.fetch()) ICloud.syncDb();
if (Stores.setting.icloudSync.fetch()) ICloud.syncDb();
if (isAndroid) {
// Only start service when [bgRun] is true.
if (locator<SettingStore>().bgRun.fetch()) {
if (Stores.setting.bgRun.fetch()) {
Miscs.bgRunChannel.invokeMethod('startService');
}
// SharedPreferences is only used on Android for saving home widgets settings.
@@ -126,6 +119,7 @@ void _setupLogger() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
var str = '[${record.loggerName}][${record.level.name}]: ${record.message}';
_debug?.addText(str);
if (record.error != null) {
str += '\n${record.error}';
_debug?.addMultiline(record.error.toString(), Colors.red);

View File

@@ -11,19 +11,16 @@ import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/data/model/app/backup.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/res/path.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import '../../core/utils/misc.dart';
import '../../data/res/ui.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
import '../widget/custom_appbar.dart';
import '../widget/store_switch.dart';
class BackupPage extends StatelessWidget {
BackupPage({Key? key}) : super(key: key);
final _setting = locator<SettingStore>();
const BackupPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@@ -118,7 +115,7 @@ class BackupPage extends StatelessWidget {
// },
// icon: const Icon(Icons.sync)),
// width13,
StoreSwitch(prop: _setting.icloudSync)
StoreSwitch(prop: Stores.setting.icloudSync)
],
);
}

View File

@@ -6,6 +6,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/route.dart';
import 'package:toolbox/data/model/docker/image.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/input_field.dart';
import '../../data/model/docker/ps.dart';
@@ -16,7 +17,6 @@ import '../../data/model/app/error.dart';
import '../../data/model/app/menu.dart';
import '../../data/res/ui.dart';
import '../../data/res/url.dart';
import '../../data/store/docker.dart';
import '../../locator.dart';
import '../widget/custom_appbar.dart';
import '../widget/popup_menu.dart';
@@ -34,7 +34,6 @@ class DockerManagePage extends StatefulWidget {
class _DockerManagePageState extends State<DockerManagePage> {
final _docker = locator<DockerProvider>();
final _store = locator<DockerStore>();
final _textController = TextEditingController();
late S _s;
@@ -479,7 +478,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
Future<void> _showEditHostDialog() async {
final id = widget.spi.id;
final host = _store.fetch(id) ?? 'unix:///run/user/1000/docker.sock';
final host = Stores.docker.fetch(id) ?? 'unix:///run/user/1000/docker.sock';
final ctrl = TextEditingController(text: host);
await context.showRoundDialog(
title: Text(_s.dockerEditHost),
@@ -499,7 +498,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
void _onSaveDockerHost(String val) {
context.pop();
_store.put(widget.spi.id, val.trim());
Stores.docker.put(widget.spi.id, val.trim());
_docker.refresh();
}
}

View File

@@ -11,8 +11,7 @@ import 'package:toolbox/core/extension/context/common.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/data/res/highlight.dart';
import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/data/res/store.dart';
import '../widget/custom_appbar.dart';
import '../widget/two_line_text.dart';
@@ -45,12 +44,12 @@ class EditorPage extends StatefulWidget {
class _EditorPageState extends State<EditorPage> {
final _focusNode = FocusNode();
final _setting = locator<SettingStore>();
late CodeController _controller;
late Map<String, TextStyle> _codeTheme;
late S _s;
late final _textStyle = TextStyle(fontSize: _setting.editorFontSize.fetch());
late final _textStyle =
TextStyle(fontSize: Stores.setting.editorFontSize.fetch());
String? _langCode;
@@ -81,9 +80,11 @@ class _EditorPageState extends State<EditorPage> {
_s = S.of(context)!;
if (context.isDark) {
_codeTheme = themeMap[_setting.editorDarkTheme.fetch()] ?? monokaiTheme;
_codeTheme =
themeMap[Stores.setting.editorDarkTheme.fetch()] ?? monokaiTheme;
} else {
_codeTheme = themeMap[_setting.editorTheme.fetch()] ?? a11yLightTheme;
_codeTheme =
themeMap[Stores.setting.editorTheme.fetch()] ?? a11yLightTheme;
}
_focusNode.requestFocus();
}

View File

@@ -10,8 +10,8 @@ import 'package:provider/provider.dart';
import 'package:toolbox/core/route.dart';
import 'package:toolbox/data/model/server/disk.dart';
import 'package:toolbox/data/provider/server.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/locator.dart';
import '../../core/analysis.dart';
@@ -39,13 +39,12 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
final _pageController = PageController(initialPage: 0);
final _serverProvider = locator<ServerProvider>();
final _setting = locator<SettingStore>();
@override
void initState() {
super.initState();
switchStatusBar(hide: true);
_rotateQuarter = _setting.fullScreenRotateQuarter.fetch();
_rotateQuarter = Stores.setting.fullScreenRotateQuarter.fetch();
_timer = Timer.periodic(const Duration(minutes: 1), (_) {
if (mounted) {
setState(() {});
@@ -88,7 +87,8 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
// `_screenWidth * 0.03` is the offset value
padding: EdgeInsets.all(_screenWidth * 0.03),
child: ValueListenableBuilder<int>(
valueListenable: _setting.fullScreenRotateQuarter.listenable(),
valueListenable:
Stores.setting.fullScreenRotateQuarter.listenable(),
builder: (_, val, __) {
_rotateQuarter = val;
return RotatedBox(
@@ -297,7 +297,7 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
Widget _buildNet(ServerStatus ss) {
return ValueListenableBuilder<NetViewType>(
valueListenable: _setting.netViewType.listenable(),
valueListenable: Stores.setting.netViewType.listenable(),
builder: (_, val, __) {
final data = val.build(ss);
return AnimatedSwitcher(
@@ -368,7 +368,7 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
@override
Future<void> afterFirstLayout(BuildContext context) async {
if (_setting.autoCheckAppUpdate.fetch()) {
if (Stores.setting.autoCheckAppUpdate.fetch()) {
doUpdate(context);
}
await GetIt.I.allReady();

View File

@@ -7,6 +7,7 @@ import 'package:get_it/get_it.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/data/res/github_id.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/res/store.dart';
import '../../core/analysis.dart';
import '../../core/route.dart';
@@ -21,7 +22,6 @@ import '../../data/res/build_data.dart';
import '../../data/res/misc.dart';
import '../../data/res/ui.dart';
import '../../data/res/url.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
import '../widget/custom_appbar.dart';
import '../widget/round_rect_card.dart';
@@ -41,7 +41,6 @@ class _HomePageState extends State<HomePage>
AfterLayoutMixin,
WidgetsBindingObserver {
final _serverProvider = locator<ServerProvider>();
final _setting = locator<SettingStore>();
final _app = locator<AppProvider>();
late final PageController _pageController;
@@ -56,7 +55,7 @@ class _HomePageState extends State<HomePage>
super.initState();
switchStatusBar(hide: false);
WidgetsBinding.instance.addObserver(this);
_selectIndex.value = _setting.launchPage.fetch();
_selectIndex.value = Stores.setting.launchPage.fetch();
// avoid index out of range
if (_selectIndex.value >= AppTab.values.length || _selectIndex.value < 0) {
_selectIndex.value = 0;
@@ -92,7 +91,7 @@ class _HomePageState extends State<HomePage>
break;
case AppLifecycleState.paused:
// Keep running in background on Android device
if (isAndroid && _setting.bgRun.fetch()) {
if (isAndroid && Stores.setting.bgRun.fetch()) {
if (_app.moveBg) {
Miscs.bgRunChannel.invokeMethod('sendToBackground');
}
@@ -210,7 +209,8 @@ class _HomePageState extends State<HomePage>
TextButton(
onPressed: () => context.showRoundDialog(
title: Text(_versionStr),
child: const Text(BuildData.buildAt),
child: const Text(
'${BuildData.buildAt}\nFlutter ${BuildData.engine}'),
),
child: Text(
'${BuildData.name}\n$_versionStr',
@@ -333,7 +333,7 @@ class _HomePageState extends State<HomePage>
if (BuildData.modifications != 0) {
mod = '(+${BuildData.modifications})';
}
return 'Ver: 1.0.${BuildData.build}$mod';
return 'v1.0.${BuildData.build}$mod';
}
@override
@@ -341,7 +341,7 @@ class _HomePageState extends State<HomePage>
@override
Future<void> afterFirstLayout(BuildContext context) async {
if (_setting.autoCheckAppUpdate.fetch()) {
if (Stores.setting.autoCheckAppUpdate.fetch()) {
doUpdate(context);
}
updateHomeWidget();
@@ -354,14 +354,14 @@ class _HomePageState extends State<HomePage>
}
void updateHomeWidget() {
if (_setting.autoUpdateHomeWidget.fetch()) {
if (Stores.setting.autoUpdateHomeWidget.fetch()) {
Miscs.homeWidgetChannel.invokeMethod('update');
}
}
Future<void> _onLongPressSetting() async {
/// Encode [map] to String with indent `\t`
final map = _setting.toJson();
final map = Stores.setting.toJson();
final keys = map.keys;
final text = Miscs.jsonEncoder.convert(map);
final result = await AppRoute.editor(
@@ -374,11 +374,11 @@ class _HomePageState extends State<HomePage>
}
try {
final newSettings = json.decode(result) as Map<String, dynamic>;
_setting.box.putAll(newSettings);
Stores.setting.box.putAll(newSettings);
final newKeys = newSettings.keys;
final removedKeys = keys.where((e) => !newKeys.contains(e));
for (final key in removedKeys) {
_setting.box.delete(key);
Stores.setting.box.delete(key);
}
} catch (e, trace) {
context.showRoundDialog(

View File

@@ -6,8 +6,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context/common.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/data/store/private_key.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/route.dart';
import '../../../core/utils/platform.dart';
@@ -83,9 +82,8 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
}
void autoAddSystemPriavteKey() {
final store = locator<PrivateKeyStore>();
// Only trigger on desktop platform and no private key saved
if (isDesktop && store.box.keys.isEmpty) {
if (isDesktop && Stores.snippet.box.keys.isEmpty) {
final home = getHomeDir();
if (home == null) return;
final idRsaFile = File(joinPath(home, '.ssh/id_rsa'));

View File

@@ -8,13 +8,13 @@ import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/extension/uint8list.dart';
import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/data/res/store.dart';
import '../../data/model/app/shell_func.dart';
import '../../data/model/server/proc.dart';
import '../../data/model/server/server_private_info.dart';
import '../../data/provider/server.dart';
import '../../data/res/ui.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
import '../widget/custom_appbar.dart';
import '../widget/round_rect_card.dart';
@@ -33,8 +33,6 @@ class _ProcessPageState extends State<ProcessPage> {
late Timer _timer;
late MediaQueryData _media;
final _setting = locator<SettingStore>();
SSHClient? _client;
PsResult _result = const PsResult(procs: []);
@@ -53,7 +51,7 @@ class _ProcessPageState extends State<ProcessPage> {
super.initState();
_client = _serverProvider.servers[widget.spi.id]?.client;
final duration =
Duration(seconds: _setting.serverStatusUpdateInterval.fetch());
Duration(seconds: Stores.setting.serverStatusUpdateInterval.fetch());
_timer = Timer.periodic(duration, (_) => _refresh());
}

View File

@@ -6,6 +6,7 @@ import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/data/model/server/cpu.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/server_func_btns.dart';
import '../../../core/extension/numx.dart';
@@ -17,8 +18,6 @@ import '../../../data/provider/server.dart';
import '../../../data/res/color.dart';
import '../../../data/res/default.dart';
import '../../../data/res/ui.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/custom_appbar.dart';
import '../../widget/round_rect_card.dart';
@@ -36,9 +35,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
late MediaQueryData _media;
late S _s;
final Order<String> _cardsOrder = [];
final _setting = locator<SettingStore>();
late final _textFactor = _setting.textFactor.fetch();
late final _textFactor = Stores.setting.textFactor.fetch();
late final _cardBuildMap = Map.fromIterables(
Defaults.detailCardOrder,
@@ -63,7 +61,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
@override
void initState() {
super.initState();
_cardsOrder.addAll(_setting.detailCardOrder.fetch());
_cardsOrder.addAll(Stores.setting.detailCardOrder.fetch());
}
@override
@@ -82,7 +80,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
}
Widget _buildMainPage(Server si) {
final buildFuncs = !_setting.moveOutServerTabFuncBtns.fetch();
final buildFuncs = !Stores.setting.moveOutServerTabFuncBtns.fetch();
return Scaffold(
appBar: CustomAppBar(
title: Text(si.spi.name, style: UIs.textSize18),
@@ -309,7 +307,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
Widget _buildDiskView(ServerStatus ss) {
final disk = ss.disk;
disk.removeWhere((e) {
for (final ingorePath in _setting.diskIgnorePath.fetch()) {
for (final ingorePath in Stores.setting.diskIgnorePath.fetch()) {
if (e.path.startsWith(ingorePath)) return true;
}
return false;

View File

@@ -8,6 +8,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/media_queryx.dart';
import 'package:toolbox/core/extension/ssh_client.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/route.dart';
import '../../../core/utils/misc.dart';
@@ -20,7 +21,6 @@ import '../../../data/model/server/server_status.dart';
import '../../../data/provider/server.dart';
import '../../../data/res/color.dart';
import '../../../data/res/ui.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/round_rect_card.dart';
import '../../widget/server_func_btns.dart';
@@ -40,7 +40,6 @@ class _ServerPageState extends State<ServerPage>
final _flipedCardIds = <String>{};
final _serverProvider = locator<ServerProvider>();
final _setting = locator<SettingStore>();
String? _tag;
bool _useDoubleColumn = false;
@@ -83,7 +82,8 @@ class _ServerPageState extends State<ServerPage>
}
final filtered = _filterServers(pro);
if (_useDoubleColumn && _setting.doubleColumnServersPage.fetch()) {
if (_useDoubleColumn &&
Stores.setting.doubleColumnServersPage.fetch()) {
return _buildBodyMedium(pro);
}
return _buildBodySmall(provider: pro, filtered: filtered);
@@ -290,9 +290,9 @@ class _ServerPageState extends State<ServerPage>
),
),
UIs.height13,
if (_setting.moveOutServerTabFuncBtns.fetch() &&
if (Stores.setting.moveOutServerTabFuncBtns.fetch() &&
// Discussion #146
!_setting.serverTabUseOldUI.fetch())
!Stores.setting.serverTabUseOldUI.fetch())
SizedBox(
height: 27,
child: ServerFuncBtns(spi: spi, s: _s),
@@ -318,7 +318,7 @@ class _ServerPageState extends State<ServerPage>
),
),
);
} else if (_setting.serverTabUseOldUI.fetch()) {
} else if (Stores.setting.serverTabUseOldUI.fetch()) {
rightCorner = ServerFuncBtnsTopRight(spi: spi, s: _s);
}
return Padding(
@@ -392,7 +392,7 @@ class _ServerPageState extends State<ServerPage>
Widget _buildNet(ServerStatus ss) {
return ValueListenableBuilder<NetViewType>(
valueListenable: _setting.netViewType.listenable(),
valueListenable: Stores.setting.netViewType.listenable(),
builder: (_, val, __) {
final data = val.build(ss);
return AnimatedSwitcher(
@@ -510,9 +510,9 @@ class _ServerPageState extends State<ServerPage>
if (_flipedCardIds.contains(id)) {
return 77.0;
}
if (_setting.moveOutServerTabFuncBtns.fetch() &&
if (Stores.setting.moveOutServerTabFuncBtns.fetch() &&
// Discussion #146
!_setting.serverTabUseOldUI.fetch()) {
!Stores.setting.serverTabUseOldUI.fetch()) {
return 132;
}
return 107;

View File

@@ -12,6 +12,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/extension/locale.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/stringx.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/persistant_store.dart';
import '../../../core/route.dart';
@@ -25,8 +26,6 @@ import '../../../data/res/build_data.dart';
import '../../../data/res/color.dart';
import '../../../data/res/path.dart';
import '../../../data/res/ui.dart';
import '../../../data/store/server.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/color_picker.dart';
import '../../widget/custom_appbar.dart';
@@ -53,9 +52,9 @@ class _SettingPageState extends State<SettingPage> {
final _keyboardTypeKey = GlobalKey<PopupMenuButtonState<int>>();
final _rotateQuarterKey = GlobalKey<PopupMenuButtonState<int>>();
final _netViewTypeKey = GlobalKey<PopupMenuButtonState<NetViewType>>();
final _serverProvider = locator<ServerProvider>();
final _setting = Stores.setting;
late final SettingStore _setting;
late final ServerProvider _serverProvider;
late S _s;
late SharedPreferences _sp;
@@ -89,8 +88,6 @@ class _SettingPageState extends State<SettingPage> {
@override
void initState() {
super.initState();
_serverProvider = locator<ServerProvider>();
_setting = locator<SettingStore>();
_nightMode.value = _setting.themeMode.fetch();
_updateInterval.value = _setting.serverStatusUpdateInterval.fetch();
_maxRetryCount.value = _setting.maxRetryCount.fetch();
@@ -964,7 +961,7 @@ class _SettingPageState extends State<SettingPage> {
title: Text(_s.deleteServers),
trailing: const Icon(Icons.delete_forever),
onTap: () async {
final all = locator<ServerStore>().box.keys.map(
final all = Stores.server.box.keys.map(
(e) => TextButton(
onPressed: () => context.showRoundDialog(
title: Text(_s.attention),

View File

@@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/extension/order.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/custom_appbar.dart';
import '../../widget/round_rect_card.dart';
@@ -15,8 +14,6 @@ class ServerDetailOrderPage extends StatefulWidget {
}
class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
final _store = locator<SettingStore>();
final Order<String> _cardsOrder = [];
late S _s;
@@ -30,7 +27,7 @@ class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
@override
void initState() {
super.initState();
_cardsOrder.addAll(_store.detailCardOrder.fetch());
_cardsOrder.addAll(Stores.setting.detailCardOrder.fetch());
}
@override
@@ -50,7 +47,7 @@ class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
_cardsOrder.move(
oldIndex,
newIndex,
property: _store.detailCardOrder,
property: Stores.setting.detailCardOrder,
);
}),
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),

View File

@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import '../../../data/provider/server.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/custom_appbar.dart';
@@ -16,7 +16,6 @@ class ServerOrderPage extends StatefulWidget {
}
class _ServerOrderPageState extends State<ServerOrderPage> {
final _store = locator<SettingStore>();
final _provider = locator<ServerProvider>();
late S _s;
@@ -44,7 +43,7 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
_provider.serverOrder.move(
oldIndex,
newIndex,
property: _store.serverOrder,
property: Stores.setting.serverOrder,
);
}),
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),

View File

@@ -4,9 +4,8 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/data/model/ssh/virtual_key.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import '../../widget/custom_appbar.dart';
@@ -19,7 +18,6 @@ class SSHVirtKeySettingPage extends StatefulWidget {
}
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
final _setting = locator<SettingStore>();
late S _s;
@override
@@ -39,7 +37,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
}
Widget _buildBody() {
final keys_ = _setting.sshVirtKeys.fetch();
final keys_ = Stores.setting.sshVirtKeys.fetch();
final keys = <VirtKey>[];
for (final key in keys_) {
keys.add(key);
@@ -67,7 +65,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
context.showSnackBar(_s.disabled);
return;
}
keys.moveByItem(keys, o, n, property: _setting.sshVirtKeys);
keys.moveByItem(keys, o, n, property: Stores.setting.sshVirtKeys);
setState(() {});
},
);
@@ -99,7 +97,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
} else {
keys.remove(key);
}
_setting.sshVirtKeys.put(keys);
Stores.setting.sshVirtKeys.put(keys);
setState(() {});
},
);

View File

@@ -3,13 +3,13 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/utils/misc.dart';
import '../../../data/model/server/server.dart';
import '../../../data/model/server/snippet.dart';
import '../../../data/provider/server.dart';
import '../../../data/res/ui.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/tag.dart';
import '/core/route.dart';
@@ -27,8 +27,6 @@ class _SnippetListPageState extends State<SnippetListPage> {
late S _s;
late MediaQueryData _media;
final _settingStore = locator<SettingStore>();
String? _tag;
@override
@@ -72,7 +70,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
oldIdx,
newIdx,
onMove: (p0) {
_settingStore.snippetOrder.put(p0.map((e) => e.name).toList());
Stores.setting.snippetOrder.put(p0.map((e) => e.name).toList());
},
);
}),

View File

@@ -10,7 +10,9 @@ import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context/common.dart';
import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:xterm/xterm.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:xterm/core.dart';
import 'package:xterm/ui.dart' hide TerminalThemes;
import '../../core/route.dart';
import '../../core/utils/platform.dart';
@@ -21,7 +23,6 @@ import '../../data/model/ssh/virtual_key.dart';
import '../../data/provider/virtual_keyboard.dart';
import '../../data/res/color.dart';
import '../../data/res/terminal.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
const echoPWD = 'echo \$PWD';
@@ -37,7 +38,6 @@ class SSHPage extends StatefulWidget {
class _SSHPageState extends State<SSHPage> {
final _keyboard = locator<VirtualKeyboard>();
final _setting = locator<SettingStore>();
late final _terminal = Terminal(inputHandler: _keyboard);
final TerminalController _terminalController = TerminalController();
final List<List<VirtKey>> _virtKeysList = [];
@@ -59,13 +59,13 @@ class _SSHPageState extends State<SSHPage> {
@override
void initState() {
super.initState();
final fontFamilly = getFileName(_setting.fontPath.fetch());
final fontFamilly = getFileName(Stores.setting.fontPath.fetch());
final textStyle = TextStyle(
fontFamily: fontFamilly,
fontSize: _setting.termFontSize.fetch(),
fontSize: Stores.setting.termFontSize.fetch(),
);
_terminalStyle = TerminalStyle.fromTextStyle(textStyle);
_keyboardType = TextInputType.values[_setting.keyboardType.fetch()];
_keyboardType = TextInputType.values[Stores.setting.keyboardType.fetch()];
_initTerminal();
_initVirtKeys();
}
@@ -89,7 +89,7 @@ class _SSHPageState extends State<SSHPage> {
_isDark = context.isDark;
_media = MediaQuery.of(context);
_s = S.of(context)!;
_terminalTheme = _isDark ? termDarkTheme : termLightTheme;
_terminalTheme = _isDark ? TerminalThemes.dark : TerminalThemes.light;
// Because the virtual keyboard only displayed on mobile devices
if (isMobile) {
@@ -299,7 +299,7 @@ class _SSHPageState extends State<SSHPage> {
}
void _initVirtKeys() {
final virtKeys = List<VirtKey>.from(_setting.sshVirtKeys.fetch());
final virtKeys = List<VirtKey>.from(Stores.setting.sshVirtKeys.fetch());
for (int len = 0; len < virtKeys.length; len += 7) {
if (len + 7 > virtKeys.length) {
@@ -326,7 +326,7 @@ class _SSHPageState extends State<SSHPage> {
return _write('Sending password to auth...');
}
},
timeout: _setting.timeoutD,
timeout: Stores.setting.timeoutD,
);
_write('Connected\r\n');
_write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n');

View File

@@ -10,7 +10,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/extension/sftpfile.dart';
import 'package:toolbox/data/res/logger.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/data/store/history.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import '../../../core/extension/numx.dart';
@@ -26,7 +26,6 @@ import '../../../data/provider/server.dart';
import '../../../data/provider/sftp.dart';
import '../../../data/res/path.dart';
import '../../../data/res/ui.dart';
import '../../../data/store/setting.dart';
import '../../../locator.dart';
import '../../widget/custom_appbar.dart';
import '../../widget/fade_in.dart';
@@ -53,8 +52,6 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
final SftpBrowserStatus _status = SftpBrowserStatus();
final _sftp = locator<SftpProvider>();
final _history = locator<HistoryStore>();
final _setting = locator<SettingStore>();
late S _s;
@@ -228,10 +225,10 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
title: Text(_s.goto),
child: Autocomplete<String>(
optionsBuilder: (val) {
if (!_setting.recordHistory.fetch()) {
if (!Stores.setting.recordHistory.fetch()) {
return [];
}
return _history.sftpPath.all.where(
return Stores.history.sftpPath.all.where(
(element) => element.contains(val.text),
);
},
@@ -254,7 +251,9 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
_status.path?.update(p);
final suc = await _listDir(path: p);
if (suc && _setting.recordHistory.fetch()) _history.sftpPath.add(p);
if (suc && Stores.setting.recordHistory.fetch()) {
Stores.history.sftpPath.add(p);
}
},
icon: const Icon(Icons.gps_fixed),
);
@@ -429,7 +428,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _delete(BuildContext context, SftpName file) {
context.pop();
final isDir = file.attr.isDirectory;
final useRmrf = _setting.sftpRmrfDir.fetch();
final useRmrf = Stores.setting.sftpRmrfDir.fetch();
final dirText = (isDir && !useRmrf) ? '\n${_s.sureDirEmpty}' : '';
final text = '${_s.sureDelete(file.filename)}$dirText';
final child = Text(text);

View File

@@ -476,9 +476,9 @@
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
@@ -491,9 +491,9 @@
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
@@ -506,9 +506,9 @@
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 547;
CURRENT_PROJECT_VERSION = 550;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0.547;
MARKETING_VERSION = 1.0.550;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;

View File

@@ -76,7 +76,7 @@ Future<Map<String, dynamic>> getBuildData() async {
'name': appName,
'build': build,
'engine': await getFlutterVersion(),
'buildAt': DateTime.now().toString(),
'buildAt': DateTime.now().toString().split('.')[0],
'modifications': await getGitModificationCount(),
'script': await getScriptCommitCount(),
};