Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scripts/test_queue_dart.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ def main():
harness = Path(folder)
(harness/'test').mkdir()
ui = ' material_ui: 1.5.0\n cupertino_ui: 1.1.1\n' if args.widgets else ''
(harness/'pubspec.yaml').write_text("name: queue_protocol_checks\nenvironment:\n sdk: '>=3.11.0 <4.0.0'\ndependencies:\n flutter:\n sdk: flutter\n"+ui+"dev_dependencies:\n flutter_test:\n sdk: flutter\n")
(harness/'pubspec.yaml').write_text("name: queue_protocol_checks\nenvironment:\n sdk: '>=3.11.0 <4.0.0'\ndependencies:\n flutter:\n sdk: flutter\n"+ui+"dev_dependencies:\n flutter_test:\n sdk: flutter\nflutter:\n uses-material-design: true\n")
names = ['queue_protocol_test.dart', 'queue_session_test.dart', 'queue_presentation_test.dart']
if args.widgets:
names.append('queue_resource_widget_test.dart')
names.append('queue_workspace_widget_test.dart')
for name in names:
source = (ROOT/'serverbox/test/unit/app'/name).read_text()
(harness/'test'/name).write_text(source)
Expand Down
20 changes: 20 additions & 0 deletions serverbox/lib/core/gpu_queue/presentation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ import 'package:server_box/core/gpu_queue/protocol.dart';
/// Human-readable queue data. Missing values stay missing, and historical GPU
/// readings never become live metrics merely because an SSH session is open.
abstract final class QueuePresentation {
static String taskStatus(Object? state) =>
const {
'ready': '待启动',
'queued': '队列中',
'waiting_gpu': '等待 GPU',
'checking_resources': '核查资源',
'dispatching': '正在投放',
'starting': '启动中',
'running': '运行中',
'stopping': '正在停止',
'stopped': '已停止',
'cancelled': '已取消',
'completed': '已完成',
'failed': '失败',
'blocked': '需核查',
'execution_unknown': '执行状态待核查',
'interrupted': '已中断',
}[state] ??
'状态待核查';

static num? _number(Object? value) =>
value is num && value.isFinite && value >= 0 ? value : null;
static String _decimal(num value) => value == value.roundToDouble()
Expand Down
114 changes: 112 additions & 2 deletions serverbox/lib/core/utils/gpu_queue_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,139 @@ ThemeData gpuQueueTheme(ThemeData base) {
onSurfaceVariant: Color(dark ? 0xFFBEB7AA : 0xFF69655E),
primary: Color(dark ? 0xFFE0A387 : 0xFF8B543E),
onPrimary: Color(dark ? 0xFF302018 : 0xFFFFFFFF),
primaryContainer: Color(dark ? 0xFF49392F : 0xFFF0E7DB),
onPrimaryContainer: Color(dark ? 0xFFF1D7C8 : 0xFF714832),
secondary: Color(dark ? 0xFF9DC8AD : 0xFF38664D),
onSecondary: Color(dark ? 0xFF153524 : 0xFFFFFFFF),
secondaryContainer: Color(dark ? 0xFF293D32 : 0xFFE7EEE3),
onSecondaryContainer: Color(dark ? 0xFFBBDDC6 : 0xFF315D45),
surfaceContainerLowest: Color(dark ? 0xFF211F1C : 0xFFFDFCF9),
surfaceContainerLow: Color(dark ? 0xFF302D28 : 0xFFFDFCF9),
surfaceContainer: Color(dark ? 0xFF35312B : 0xFFEEECE4),
surfaceContainerHigh: Color(dark ? 0xFF3B372F : 0xFFE8E4DA),
surfaceContainerHighest: Color(dark ? 0xFF444036 : 0xFFDFDAD0),
outline: Color(dark ? 0xFF8F877B : 0xFF8C8579),
outlineVariant: Color(dark ? 0xFF4A453D : 0xFFE2DED5),
);
final text = base.textTheme.apply(
bodyColor: scheme.onSurface,
displayColor: scheme.onSurface,
);
TextStyle? heading(TextStyle? style) => style?.copyWith(
fontFamily: 'Georgia',
fontFamilyFallback: const ['Songti SC', 'Noto Serif CJK SC'],
fontFamily: base.platform == TargetPlatform.linux
? 'DejaVu Serif'
: 'Georgia',
fontFamilyFallback: base.platform == TargetPlatform.linux
? const ['WenQuanYi Micro Hei', 'Noto Serif CJK SC']
: const [
'Songti SC',
'Noto Serif CJK SC',
'DejaVu Serif',
'WenQuanYi Micro Hei',
],
fontWeight: FontWeight.w500,
);
return base.copyWith(
colorScheme: scheme,
canvasColor: scheme.surface,
scaffoldBackgroundColor: scheme.surface,
cardColor: Color(dark ? 0xFF302D28 : 0xFFFDFCF9),
dividerColor: scheme.outlineVariant,
textTheme: text.copyWith(
headlineLarge: heading(text.headlineLarge),
headlineMedium: heading(text.headlineMedium),
headlineSmall: heading(text.headlineSmall),
titleLarge: heading(text.titleLarge),
titleMedium: text.titleMedium?.copyWith(
fontSize: 15,
fontWeight: FontWeight.w600,
height: 1.5,
),
bodyLarge: text.bodyLarge?.copyWith(fontSize: 15, height: 1.7),
bodyMedium: text.bodyMedium?.copyWith(fontSize: 14, height: 1.6),
bodySmall: text.bodySmall?.copyWith(
fontSize: 12,
height: 1.6,
color: scheme.onSurfaceVariant,
),
),
appBarTheme: base.appBarTheme.copyWith(
backgroundColor: scheme.surface,
foregroundColor: scheme.onSurface,
surfaceTintColor: Colors.transparent,
elevation: 0,
scrolledUnderElevation: 0,
titleTextStyle: text.titleMedium?.copyWith(
fontSize: 18,
fontWeight: FontWeight.w600,
color: scheme.onSurface,
),
),
cardTheme: CardThemeData(
elevation: 0,
color: scheme.surfaceContainerLow,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(color: scheme.outlineVariant),
),
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
minimumSize: const Size(44, 44),
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
minimumSize: const Size(44, 44),
foregroundColor: scheme.onSurface,
backgroundColor: scheme.surfaceContainerLow,
side: BorderSide(color: scheme.outlineVariant),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
inputDecorationTheme: base.inputDecorationTheme.copyWith(
filled: true,
fillColor: scheme.surfaceContainerLow,
contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: scheme.outlineVariant),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: scheme.outlineVariant),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: scheme.primary, width: 2),
),
),
chipTheme: base.chipTheme.copyWith(
backgroundColor: scheme.surfaceContainerLow,
selectedColor: scheme.secondaryContainer,
side: BorderSide(color: scheme.outlineVariant),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
),
listTileTheme: base.listTileTheme.copyWith(
selectedColor: scheme.primary,
selectedTileColor: scheme.primaryContainer,
),
navigationRailTheme: base.navigationRailTheme.copyWith(
backgroundColor: scheme.surface,
indicatorColor: scheme.primaryContainer,
),
navigationBarTheme: base.navigationBarTheme.copyWith(
backgroundColor: scheme.surface,
indicatorColor: scheme.primaryContainer,
surfaceTintColor: Colors.transparent,
),
dialogTheme: base.dialogTheme.copyWith(
backgroundColor: scheme.surfaceContainerLow,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),
);
}
Loading