feat: Windows compatibility (#836)

* 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>
This commit is contained in:
lollipopkit🏳️‍⚧️
2025-08-08 16:56:36 +08:00
committed by GitHub
parent 46a12bc844
commit 3a615449e3
103 changed files with 9591 additions and 1906 deletions

View File

@@ -51,30 +51,30 @@ enum VirtKey {
f9,
f10,
f11,
f12;
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,
};
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 {
@@ -111,74 +111,74 @@ extension VirtKeyX on VirtKey {
/// 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,
};
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,
};
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,
};
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,
};
VirtKey.alt || VirtKey.ctrl || VirtKey.shift => true,
_ => false,
};
bool get canLongPress => switch (this) {
VirtKey.up || VirtKey.left || VirtKey.down || VirtKey.right => true,
_ => false,
};
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,
};
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}) {