Files
flutter_server_box/lib/data/model/container/image.dart
lollipopkit🏳️‍⚧️ 3a615449e3 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>
2025-08-08 16:56:36 +08:00

122 lines
2.9 KiB
Dart

import 'dart:convert';
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/container/type.dart';
abstract final class ContainerImg {
final String? repository = null;
final String? tag = null;
final String? id = null;
String? get sizeMB;
int? get containersCount;
factory ContainerImg.fromRawJson(String s, ContainerType typ) => typ.img(s);
}
final class PodmanImg implements ContainerImg {
@override
final String? repository;
@override
final String? tag;
@override
final String? id;
final int? created;
final int? size;
final int? containers;
PodmanImg({this.repository, this.tag, this.id, this.created, this.size, this.containers});
@override
String? get sizeMB => size?.bytes2Str;
@override
int? get containersCount => containers;
factory PodmanImg.fromRawJson(String str) => PodmanImg.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory PodmanImg.fromJson(Map<String, dynamic> json) => PodmanImg(
repository: json['repository'],
tag: json['tag'],
id: json['Id'],
created: json['Created'],
size: json['Size'],
containers: json['Containers'],
);
Map<String, dynamic> toJson() => {
'repository': repository,
'tag': tag,
'Id': id,
'Created': created,
'Size': size,
'Containers': containers,
};
}
final class DockerImg implements ContainerImg {
final String containers;
final String createdAt;
@override
final String id;
@override
final String repository;
final String size;
@override
final String? tag;
DockerImg({
required this.containers,
required this.createdAt,
required this.id,
required this.repository,
required this.size,
required this.tag,
});
@override
String? get sizeMB => size;
@override
int? get containersCount => containers == 'N/A' ? 0 : int.tryParse(containers);
factory DockerImg.fromRawJson(String str) => DockerImg.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory DockerImg.fromJson(Map<String, dynamic> json) {
final containers = switch (json['Containers']) {
final String a => a,
final Object? a => a.toString(),
};
final repo = switch (json['Repository'] ?? json['Names']) {
final String a => a,
final List a => a.firstOrNull.toString(),
final Object? a => a.toString(),
};
final size = switch (json['Size']) {
final String a => a,
final int a => a.bytes2Str,
final Object? a => a.toString(),
};
return DockerImg(
containers: containers,
createdAt: json['CreatedAt'],
id: json['ID'] ?? json['Id'] ?? '',
repository: repo,
size: size,
tag: json['Tag'],
);
}
Map<String, dynamic> toJson() => {
'Containers': containers,
'CreatedAt': createdAt,
'ID': id,
'Repository': repository,
'Size': size,
'Tag': tag,
};
}