Files
moonwell-launcher/widgetbook/lib/stories/launcher_stories.dart
T

231 lines
7.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:moonwell_launcher/app/design_system/mw_launcher_components.dart';
import 'package:moonwell_launcher/core/moonwell_theme_variant.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook;
@widgetbook.UseCase(name: 'interactive', type: MwGameTile, path: '[Launcher]')
Widget buildMwGameTileInteractiveUseCase(BuildContext context) {
return SizedBox(
width: context.knobs.double.slider(
label: 'width',
initialValue: 240,
min: 72,
max: 360,
divisions: 36,
),
child: MwGameTile(
title: context.knobs.string(label: 'title', initialValue: 'MoonWell'),
subtitle: context.knobs.stringOrNull(
label: 'subtitle',
initialValue: 'Wrath of the Lich King',
),
icon: Icons.nights_stay_outlined,
selected: context.knobs.boolean(label: 'selected', initialValue: true),
enabled: context.knobs.boolean(label: 'enabled', initialValue: true),
compact: context.knobs.boolean(label: 'compact', initialValue: false),
onPressed: () => debugPrint('Game tile selected'),
),
);
}
@widgetbook.UseCase(name: 'full', type: MwGameRail, path: '[Launcher]')
Widget buildMwGameRailFullUseCase(BuildContext context) {
return const SizedBox(width: 240, height: 560, child: MwGameRail());
}
@widgetbook.UseCase(name: 'compact', type: MwGameRail, path: '[Launcher]')
Widget buildMwGameRailCompactUseCase(BuildContext context) {
return const SizedBox(
width: 72,
height: 560,
child: MwGameRail(compact: true),
);
}
@widgetbook.UseCase(name: 'text_only', type: MwNewsItem, path: '[Launcher]')
Widget buildMwNewsItemTextOnlyUseCase(BuildContext context) {
return SizedBox(
width: 620,
child: MwNewsItem(
item: MwNewsItemData(
title: context.knobs.string(
label: 'title',
initialValue: 'Добро пожаловать в MoonWell',
),
body: context.knobs.string(
label: 'body',
initialValue: 'Приключение в Нордсколе начинается здесь.',
),
createdAt: DateTime(2026, 6, 22),
),
),
);
}
@widgetbook.UseCase(name: 'image_failure', type: MwNewsItem, path: '[Launcher]')
Widget buildMwNewsItemImageFailureUseCase(BuildContext context) {
return const SizedBox(
width: 620,
child: MwNewsItem(
item: MwNewsItemData(
title: 'Обновление игрового мира',
body: 'Изображение недоступно, но публикация остаётся читаемой.',
imageUrl: 'https://invalid.moonwell.local/news.jpg',
),
),
);
}
@widgetbook.UseCase(name: 'loading', type: MwNewsList, path: '[Launcher]')
Widget buildMwNewsListLoadingUseCase(BuildContext context) {
return const MwNewsList(state: MwNewsListState.loading);
}
@widgetbook.UseCase(name: 'empty', type: MwNewsList, path: '[Launcher]')
Widget buildMwNewsListEmptyUseCase(BuildContext context) {
return const MwNewsList(state: MwNewsListState.empty);
}
@widgetbook.UseCase(name: 'failure', type: MwNewsList, path: '[Launcher]')
Widget buildMwNewsListFailureUseCase(BuildContext context) {
return MwNewsList(
state: MwNewsListState.failure,
error: context.knobs.string(
label: 'error',
initialValue: 'Сервер новостей временно недоступен.',
),
onRetry: () => debugPrint('News reload requested'),
);
}
@widgetbook.UseCase(name: 'populated', type: MwNewsList, path: '[Launcher]')
Widget buildMwNewsListPopulatedUseCase(BuildContext context) {
final count = context.knobs.int.slider(
label: 'itemCount',
initialValue: 8,
min: 1,
max: 50,
divisions: 49,
);
return MwNewsList(
state: MwNewsListState.populated,
items: List.generate(
count,
(index) => MwNewsItemData(
title: 'Новость ${index + 1}',
body:
'Реалистичный текст публикации о событиях и обновлениях MoonWell.',
createdAt: DateTime(2026, 6, 22).subtract(Duration(days: index)),
),
),
);
}
@widgetbook.UseCase(
name: 'interactive',
type: MwSyncActionArea,
path: '[Launcher]',
)
Widget buildMwSyncActionAreaInteractiveUseCase(BuildContext context) {
final state = context.knobs.object.dropdown<MwSyncPresentation>(
label: 'state',
initialOption: MwSyncPresentation.downloading,
options: MwSyncPresentation.values,
labelBuilder: (value) => value.name,
);
return SizedBox(
width: 420,
child: MwSyncActionArea(
state: state,
status: context.knobs.string(
label: 'status',
initialValue: 'Загружаем обновление клиента…',
),
progress: context.knobs.double.slider(
label: 'progress',
initialValue: .46,
min: 0,
max: 1,
divisions: 100,
),
currentPath: context.knobs.stringOrNull(
label: 'currentPath',
initialValue: r'Data\ruRU\patch-ruRU.MPQ',
),
error: state == MwSyncPresentation.failure
? context.knobs.string(
label: 'error',
initialValue: 'Проверка SHA-256 не пройдена.',
)
: null,
onPrimary: () => debugPrint('Primary sync action requested: $state'),
onPause: state == MwSyncPresentation.downloading
? () => debugPrint('Sync pause requested')
: null,
),
);
}
@widgetbook.UseCase(
name: 'metadata',
type: MwLauncherStatusBar,
path: '[Launcher]',
)
Widget buildMwLauncherStatusBarMetadataUseCase(BuildContext context) {
return MwLauncherStatusBar(
status: context.knobs.string(
label: 'status',
initialValue: 'Загрузка игровых файлов',
),
fileCount: 'Файлы 124/480',
speed: '12.4 MB/s',
eta: 'ETA 00:01:42',
buildHash: 'a93fd1c2',
);
}
@widgetbook.UseCase(
name: 'default',
type: MwAccountAffordance,
path: '[Launcher]',
)
Widget buildMwAccountAffordanceUseCase(BuildContext context) {
return MwAccountAffordance(
onSettings: () => debugPrint('Settings requested'),
onLogout: () => debugPrint('Logout requested'),
);
}
@widgetbook.UseCase(
name: 'interactive',
type: MwSettingsPanel,
path: '[Launcher]',
)
Widget buildMwSettingsPanelInteractiveUseCase(BuildContext context) {
final variant = context.knobs.object.dropdown<MoonWellThemeVariant>(
label: 'themeVariant',
initialOption: MoonWellThemeVariant.forest,
options: MoonWellThemeVariant.values,
labelBuilder: (value) => value.name,
);
return SizedBox(
width: 420,
child: MwSettingsPanel(
installationPath: context.knobs.stringOrNull(
label: 'installationPath',
initialValue: r'C:\Games\MoonWell',
),
themeVariant: variant,
syncActive: context.knobs.boolean(
label: 'syncActive',
initialValue: false,
),
onChooseDirectory: () => debugPrint('Directory selection requested'),
onThemeChanged: (value) => debugPrint('Theme changed: ${value.name}'),
onVerify: () => debugPrint('Manual verification requested'),
onLogout: () => debugPrint('Logout requested'),
),
);
}