mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-16 23:04:22 +01:00
* feat: win compatibility * fix * fix: uptime parse * opt.: linux uptime accuracy * fix: windows temperature fetching * opt. * opt.: powershell exec * refactor: address PR review feedback and improve code quality ### Major Improvements: - **Refactored Windows status parsing**: Broke down large `_getWindowsStatus` method into 13 smaller, focused helper methods for better maintainability and readability - **Extracted system detection logic**: Created dedicated `SystemDetector` helper class to separate OS detection concerns from ServerProvider - **Improved concurrency handling**: Implemented proper synchronization for server updates using Future-based locks to prevent race conditions ### Bug Fixes: - **Fixed CPU percentage parsing**: Removed incorrect '*100' multiplication in BSD CPU parsing (values were already percentages) - **Enhanced memory parsing**: Added validation and error handling to BSD memory fallback parsing with proper logging - **Improved uptime parsing**: Added support for multiple Windows date formats and robust error handling with validation - **Fixed division by zero**: Added safety checks in Swap.usedPercent getter ### Code Quality Enhancements: - **Added comprehensive documentation**: Documented Windows CPU counter limitations and approach - **Strengthened error handling**: Added detailed logging and validation throughout parsing methods - **Improved robustness**: Enhanced BSD CPU parsing with percentage validation and warnings - **Better separation of concerns**: Each parsing method now has single responsibility ### Files Changed: - `lib/data/helper/system_detector.dart` (new): System detection helper - `lib/data/model/server/cpu.dart`: Fixed percentage parsing and added validation - `lib/data/model/server/memory.dart`: Enhanced fallback parsing and division-by-zero protection - `lib/data/model/server/server_status_update_req.dart`: Refactored into 13 focused parsing methods - `lib/data/provider/server.dart`: Improved synchronization and extracted system detection 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: parse & shell fn struct --------- Co-authored-by: Claude <noreply@anthropic.com>
197 lines
4.7 KiB
Dart
197 lines
4.7 KiB
Dart
import 'package:fl_lib/fl_lib.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:server_box/core/extension/context/locale.dart';
|
|
import 'package:server_box/data/res/store.dart';
|
|
import 'package:xterm/core.dart';
|
|
|
|
enum VirtualKeyFunc { toggleIME, backspace, clipboard, snippet, file }
|
|
|
|
enum VirtKey {
|
|
esc,
|
|
alt,
|
|
home,
|
|
up,
|
|
end,
|
|
sftp,
|
|
snippet,
|
|
tab,
|
|
ctrl,
|
|
left,
|
|
down,
|
|
right,
|
|
clipboard,
|
|
ime,
|
|
shift,
|
|
pgup,
|
|
pgdn,
|
|
slash,
|
|
backSlash,
|
|
underscore,
|
|
plus,
|
|
equal,
|
|
minus,
|
|
parenLeft,
|
|
parenRight,
|
|
bracketLeft,
|
|
bracketRight,
|
|
braceLeft,
|
|
braceRight,
|
|
chevronLeft,
|
|
chevronRight,
|
|
colon,
|
|
semicolon,
|
|
f1,
|
|
f2,
|
|
f3,
|
|
f4,
|
|
f5,
|
|
f6,
|
|
f7,
|
|
f8,
|
|
f9,
|
|
f10,
|
|
f11,
|
|
f12,
|
|
}
|
|
|
|
extension VirtKeyX on VirtKey {
|
|
/// Used for input to terminal
|
|
String? get inputRaw => switch (this) {
|
|
VirtKey.slash => '/',
|
|
VirtKey.backSlash => '\\',
|
|
VirtKey.underscore => '_',
|
|
VirtKey.plus => '+',
|
|
VirtKey.equal => '=',
|
|
VirtKey.minus => '-',
|
|
VirtKey.parenLeft => '(',
|
|
VirtKey.parenRight => ')',
|
|
VirtKey.bracketLeft => '[',
|
|
VirtKey.bracketRight => ']',
|
|
VirtKey.braceLeft => '{',
|
|
VirtKey.braceRight => '}',
|
|
VirtKey.chevronLeft => '<',
|
|
VirtKey.chevronRight => '>',
|
|
VirtKey.colon => ':',
|
|
VirtKey.semicolon => ';',
|
|
_ => null,
|
|
};
|
|
|
|
/// Used for displaying on UI
|
|
String get text {
|
|
final t = inputRaw;
|
|
if (t != null) return t;
|
|
|
|
if (this == VirtKey.pgdn) return 'PgDn';
|
|
if (this == VirtKey.pgup) return 'PgUp';
|
|
|
|
if (name.length > 1) {
|
|
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
/// Default order of virtual keys
|
|
static const defaultOrder = [
|
|
VirtKey.esc,
|
|
VirtKey.alt,
|
|
VirtKey.home,
|
|
VirtKey.up,
|
|
VirtKey.end,
|
|
VirtKey.sftp,
|
|
VirtKey.snippet,
|
|
VirtKey.tab,
|
|
VirtKey.ctrl,
|
|
VirtKey.left,
|
|
VirtKey.down,
|
|
VirtKey.right,
|
|
VirtKey.clipboard,
|
|
VirtKey.ime,
|
|
VirtKey.shift,
|
|
];
|
|
|
|
/// Corresponding [TerminalKey]
|
|
TerminalKey? get key => switch (this) {
|
|
VirtKey.esc => TerminalKey.escape,
|
|
VirtKey.alt => TerminalKey.alt,
|
|
VirtKey.home => TerminalKey.home,
|
|
VirtKey.up => TerminalKey.arrowUp,
|
|
VirtKey.end => TerminalKey.end,
|
|
VirtKey.tab => TerminalKey.tab,
|
|
VirtKey.ctrl => TerminalKey.control,
|
|
VirtKey.left => TerminalKey.arrowLeft,
|
|
VirtKey.down => TerminalKey.arrowDown,
|
|
VirtKey.right => TerminalKey.arrowRight,
|
|
VirtKey.shift => TerminalKey.shift,
|
|
VirtKey.pgup => TerminalKey.pageUp,
|
|
VirtKey.pgdn => TerminalKey.pageDown,
|
|
VirtKey.f1 => TerminalKey.f1,
|
|
VirtKey.f2 => TerminalKey.f2,
|
|
VirtKey.f3 => TerminalKey.f3,
|
|
VirtKey.f4 => TerminalKey.f4,
|
|
VirtKey.f5 => TerminalKey.f5,
|
|
VirtKey.f6 => TerminalKey.f6,
|
|
VirtKey.f7 => TerminalKey.f7,
|
|
VirtKey.f8 => TerminalKey.f8,
|
|
VirtKey.f9 => TerminalKey.f9,
|
|
VirtKey.f10 => TerminalKey.f10,
|
|
VirtKey.f11 => TerminalKey.f11,
|
|
VirtKey.f12 => TerminalKey.f12,
|
|
_ => null,
|
|
};
|
|
|
|
/// Icons for virtual keys
|
|
IconData? get icon => switch (this) {
|
|
VirtKey.up => Icons.arrow_upward,
|
|
VirtKey.left => Icons.arrow_back,
|
|
VirtKey.down => Icons.arrow_downward,
|
|
VirtKey.right => Icons.arrow_forward,
|
|
VirtKey.sftp => Icons.file_open,
|
|
VirtKey.snippet => Icons.code,
|
|
VirtKey.clipboard => Icons.paste,
|
|
VirtKey.ime => Icons.keyboard,
|
|
_ => null,
|
|
};
|
|
|
|
// Use [VirtualKeyFunc] instead of [VirtKey]
|
|
// This can help linter to enum all [VirtualKeyFunc]
|
|
// and make sure all [VirtualKeyFunc] are handled
|
|
VirtualKeyFunc? get func => switch (this) {
|
|
VirtKey.sftp => VirtualKeyFunc.file,
|
|
VirtKey.snippet => VirtualKeyFunc.snippet,
|
|
VirtKey.clipboard => VirtualKeyFunc.clipboard,
|
|
VirtKey.ime => VirtualKeyFunc.toggleIME,
|
|
_ => null,
|
|
};
|
|
|
|
bool get toggleable => switch (this) {
|
|
VirtKey.alt || VirtKey.ctrl || VirtKey.shift => true,
|
|
_ => false,
|
|
};
|
|
|
|
bool get canLongPress => switch (this) {
|
|
VirtKey.up || VirtKey.left || VirtKey.down || VirtKey.right => true,
|
|
_ => false,
|
|
};
|
|
|
|
String? get help => switch (this) {
|
|
VirtKey.sftp => l10n.virtKeyHelpSFTP,
|
|
VirtKey.clipboard => l10n.virtKeyHelpClipboard,
|
|
VirtKey.ime => l10n.virtKeyHelpIME,
|
|
_ => null,
|
|
};
|
|
|
|
/// - [saveDefaultIfErr] if the stored raw values is invalid, save default order to store
|
|
static List<VirtKey> loadFromStore({bool saveDefaultIfErr = true}) {
|
|
try {
|
|
final ints = Stores.setting.sshVirtKeys.fetch();
|
|
return ints.map((e) => VirtKey.values[e]).toList();
|
|
} on RangeError {
|
|
final ints = defaultOrder.map((e) => e.index).toList();
|
|
Stores.setting.sshVirtKeys.put(ints);
|
|
} catch (e, s) {
|
|
Loggers.app.warning('Failed to load sshVirtKeys', e, s);
|
|
}
|
|
return defaultOrder;
|
|
}
|
|
}
|