WIP: feat(ui): Migrate to new UI implementation

This commit is contained in:
2026-06-22 06:47:16 +04:00
parent 873aa8d7b5
commit bb4334f68d
109 changed files with 13499 additions and 1257 deletions
+447
View File
@@ -0,0 +1,447 @@
import 'package:flutter/material.dart';
import 'package:moonwell_launcher/app/design_system/mw_launcher_components.dart';
import 'package:moonwell_launcher/app/design_system/mw_window_chrome.dart';
import 'package:moonwell_launcher/app/theme/moonwell_design_system.dart';
const _ink = Color(0xFF06091A);
const _ivory = Color(0xFFECE4D0);
class MwBrandMark extends StatelessWidget {
const MwBrandMark({super.key, this.width = 220, this.compact = false});
final double width;
final bool compact;
@override
Widget build(BuildContext context) {
final accent = MoonWellDesignTokens.of(context).accent;
return Semantics(
image: true,
label: 'MoonWell',
child: SizedBox(
width: width,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
_MoonMark(size: compact ? 28 : 40, color: accent),
const SizedBox(width: 12),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'MOONWELL',
style: TextStyle(
fontFamily: 'Cinzel',
color: _ivory,
fontSize: compact ? 15 : 22,
height: 1,
letterSpacing: compact ? 4 : 6,
),
),
if (!compact) ...[
const SizedBox(height: 5),
Text(
'LUNAR · LAUNCHER',
style: TextStyle(
fontFamily: 'JetBrains Mono',
color: accent,
fontSize: 9,
letterSpacing: 2.6,
),
),
],
],
),
],
),
),
);
}
}
class _MoonMark extends StatelessWidget {
const _MoonMark({required this.size, required this.color});
final double size;
final Color color;
@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: size,
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: color.withAlpha(90)),
boxShadow: [BoxShadow(color: color.withAlpha(70), blurRadius: 16)],
),
child: Icon(Icons.nightlight_round, color: color, size: size * .72),
),
);
}
}
class MwArtworkBackground extends StatelessWidget {
const MwArtworkBackground({
super.key,
required this.child,
this.assetPackage,
});
final Widget child;
final String? assetPackage;
@override
Widget build(BuildContext context) {
final accent = MoonWellDesignTokens.of(context).accent;
return Stack(
fit: StackFit.expand,
children: [
const ColoredBox(color: _ink),
// Image.asset(
// 'assets/background.png',
// package: assetPackage,
// fit: BoxFit.cover,
// alignment: Alignment.center,
// errorBuilder: (_, _, _) => const SizedBox.shrink(),
// ),
DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
_ink.withAlpha(235),
_ink.withAlpha(85),
_ink.withAlpha(165),
],
),
),
),
DecoratedBox(
decoration: BoxDecoration(
gradient: RadialGradient(
center: const Alignment(.35, -.5),
radius: .8,
colors: [accent.withAlpha(42), Colors.transparent],
),
),
),
child,
],
);
}
}
class MwLoginShell extends StatelessWidget {
const MwLoginShell({
super.key,
required this.form,
required this.onDrag,
required this.onDoubleTap,
required this.onMinimize,
required this.onMaximizeRestore,
required this.onClose,
this.assetPackage,
});
final Widget form;
final VoidCallback onDrag;
final VoidCallback onDoubleTap;
final VoidCallback onMinimize;
final VoidCallback onMaximizeRestore;
final VoidCallback onClose;
final String? assetPackage;
@override
Widget build(BuildContext context) {
return Scaffold(
body: MwArtworkBackground(
assetPackage: assetPackage,
child: Stack(
children: [
Positioned.fill(
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(64, 80, 64, 58),
child: Align(
alignment: Alignment.bottomLeft,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
child: const Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'',
style: TextStyle(
color: Color(0xFF7FB8D4),
fontSize: 20,
),
),
SizedBox(height: 12),
Text(
'«Звёздный свет проведёт тебя сквозь самые '
'тёмные ночи — если ты готов идти туда, '
'куда он указывает.»',
style: TextStyle(
fontFamily: 'Cormorant Garamond',
fontStyle: FontStyle.italic,
color: Color(0xC6ECE4D0),
fontSize: 22,
height: 1.5,
),
),
SizedBox(height: 18),
Text(
'— МАЛФУРИОН ЯРОСТЬ БУРИ',
style: TextStyle(
fontFamily: 'JetBrains Mono',
color: Color(0x80ECE4D0),
fontSize: 10,
letterSpacing: 2,
),
),
],
),
),
),
),
),
Container(
width: 480,
decoration: const BoxDecoration(
color: Color(0xF20A0D1F),
border: Border(
left: BorderSide(color: Color(0x247FB8D4)),
),
),
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(56, 64, 56, 58),
child: form,
),
),
],
),
),
Positioned(
left: 0,
right: 0,
top: 0,
child: MwWindowChrome(
onDrag: onDrag,
onDoubleTap: onDoubleTap,
onMinimize: onMinimize,
onMaximizeRestore: onMaximizeRestore,
onClose: onClose,
showMaximize: false,
),
),
const Positioned(
left: 0,
right: 0,
bottom: 0,
height: 26,
child: _LoginStatusBar(),
),
],
),
),
);
}
}
class _LoginStatusBar extends StatelessWidget {
const _LoginStatusBar();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 32),
decoration: const BoxDecoration(
color: Color(0xD904060E),
border: Border(top: BorderSide(color: Color(0x247FB8D4))),
),
child: const Row(
children: [
Text('Версия лаунчера 1.0.0'),
SizedBox(width: 24),
Text('·'),
SizedBox(width: 24),
Text('Соединение защищено TLS'),
Spacer(),
Text('© 2026 MoonWell'),
],
),
);
}
}
class MwLauncherShell extends StatelessWidget {
const MwLauncherShell({
super.key,
required this.news,
required this.syncActions,
required this.statusBar,
required this.account,
required this.onDrag,
required this.onDoubleTap,
required this.onMinimize,
required this.onMaximizeRestore,
required this.onClose,
this.assetPackage,
});
final Widget news;
final Widget syncActions;
final Widget statusBar;
final Widget account;
final VoidCallback onDrag;
final VoidCallback onDoubleTap;
final VoidCallback onMinimize;
final VoidCallback onMaximizeRestore;
final VoidCallback onClose;
final String? assetPackage;
@override
Widget build(BuildContext context) {
return Scaffold(
body: MwArtworkBackground(
assetPackage: assetPackage,
child: Stack(
children: [
const Positioned(
left: 0,
top: 0,
bottom: 0,
width: 240,
child: MwGameRail(),
),
Positioned(
left: 272,
top: 24,
child: const MwBrandMark(width: 245),
),
Positioned(right: 28, top: 48, child: account),
const Positioned(left: 272, top: 160, child: _HeroCopy()),
Positioned(
right: 24,
top: 110,
bottom: 130,
width: 360,
child: news,
),
Positioned(
left: 240,
right: 0,
bottom: 26,
height: 110,
child: syncActions,
),
Positioned(
left: 240,
right: 0,
bottom: 0,
height: 26,
child: statusBar,
),
Positioned(
left: 0,
right: 0,
top: 0,
child: MwWindowChrome(
onDrag: onDrag,
onDoubleTap: onDoubleTap,
onMinimize: onMinimize,
onMaximizeRestore: onMaximizeRestore,
onClose: onClose,
showMaximize: false,
),
),
],
),
),
);
}
}
class _HeroCopy extends StatelessWidget {
const _HeroCopy();
@override
Widget build(BuildContext context) {
final accent = MoonWellDesignTokens.of(context).accent;
return SizedBox(
width: 520,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
border: Border.all(color: accent),
borderRadius: BorderRadius.circular(99),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 6,
height: 6,
decoration: BoxDecoration(
color: accent,
shape: BoxShape.circle,
),
),
const SizedBox(width: 10),
Text(
'OPEN BETA',
style: TextStyle(
fontFamily: 'JetBrains Mono',
color: accent,
fontSize: 11,
letterSpacing: 2.4,
),
),
],
),
),
const SizedBox(height: 18),
const Text(
'Свет колодца',
style: TextStyle(
fontFamily: 'Cinzel',
color: _ivory,
fontSize: 50,
height: 1.05,
letterSpacing: 1.5,
),
),
Text(
'зовёт тебя домой.',
style: TextStyle(
fontFamily: 'Cormorant Garamond',
fontStyle: FontStyle.italic,
color: accent,
fontSize: 54,
height: 1.05,
),
),
const SizedBox(height: 14),
const Text(
'Wrath of the Lich King · приватный сервер',
style: TextStyle(
fontFamily: 'Cormorant Garamond',
fontStyle: FontStyle.italic,
color: Color(0xC6ECE4D0),
fontSize: 18,
),
),
],
),
);
}
}