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, ), ), ], ), ); } }