import 'package:flutter/material.dart'; import 'package:playwith_core/playwith_core.dart'; // AvatarWidget 포함됨 import 'package:url_launcher/url_launcher.dart'; // [추가] 링크 이동용 class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { final _nickController = TextEditingController(); final _settings = SettingsNotifier(); @override void initState() { super.initState(); _nickController.text = _settings.nickname; } @override void dispose() { _nickController.dispose(); super.dispose(); } // [추가] 홈페이지 열기 함수 Future _launchHomepage() async { // 이동할 홈페이지 주소를 입력하세요 final Uri url = Uri.parse('https://lunaticbum.kr"'); try { if (!await launchUrl(url, mode: LaunchMode.externalApplication)) { throw Exception('Could not launch $url'); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("페이지를 열 수 없습니다.")), ); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("설정")), body: ListenableBuilder( listenable: _settings, builder: (context, _) { return ListView( padding: const EdgeInsets.all(16), children: [ // 1. 프로필 설정 섹션 _buildSectionTitle("프로필 설정"), Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ GestureDetector( onTap: () => _settings.pickProfileImage(), child: Stack( alignment: Alignment.bottomRight, children: [ AvatarWidget( base64Image: _settings.profileImageBase64, colorValue: Colors.primaries[_settings.avatarIndex % Colors.primaries.length].value, nickname: _nickController.text, size: 100, ), Container( padding: const EdgeInsets.all(6), decoration: const BoxDecoration(color: Colors.blue, shape: BoxShape.circle), child: const Icon(Icons.edit, size: 16, color: Colors.white), ), ], ), ), if (_settings.profileImageBase64 != null) TextButton( onPressed: () => _settings.clearProfileImage(), child: const Text("이미지 삭제 (기본값 사용)", style: TextStyle(color: Colors.red)), ), const SizedBox(height: 20), TextField( controller: _nickController, decoration: const InputDecoration( labelText: "닉네임", border: OutlineInputBorder(), helperText: "게임에서 사용할 이름을 입력하세요.", ), onChanged: (val) => _settings.setProfile(val, _settings.avatarIndex), ), const SizedBox(height: 10), const Align(alignment: Alignment.centerLeft, child: Text("기본 배경색")), const SizedBox(height: 5), SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: List.generate(Colors.primaries.length, (index) { final isSelected = _settings.avatarIndex == index; return GestureDetector( onTap: () => _settings.setProfile(_nickController.text, index), child: Container( margin: const EdgeInsets.only(right: 8), width: 30, height: 30, decoration: BoxDecoration( color: Colors.primaries[index], shape: BoxShape.circle, border: isSelected ? Border.all(color: Colors.black, width: 2) : null, ), child: isSelected ? const Icon(Icons.check, size: 16, color: Colors.white) : null, ), ); }), ), ), ], ), ), ), const SizedBox(height: 20), // 2. 디스플레이 설정 섹션 _buildSectionTitle("화면 설정"), Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SwitchListTile( title: const Text("다크 모드"), value: _settings.isDarkMode, onChanged: (val) => _settings.toggleDarkMode(val), ), const Divider(), const Text("글자 크기", style: TextStyle(fontWeight: FontWeight.bold)), Slider( value: _settings.fontScale, min: 0.8, max: 1.5, divisions: 7, label: "${(_settings.fontScale * 100).toInt()}%", onChanged: (val) => _settings.setFontScale(val), ), Text( "이 크기로 보입니다.", style: TextStyle(fontSize: 16 * _settings.fontScale), ), const Divider(), const Text("테마 색상", style: TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 10), Wrap( spacing: 10, runSpacing: 10, children: appColors.entries.map((entry) { final isSelected = _settings.themeColorName == entry.key; return GestureDetector( onTap: () => _settings.setThemeColor(entry.key), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: entry.value, shape: BoxShape.circle, border: isSelected ? Border.all(color: Colors.black, width: 3) : null, boxShadow: [if(isSelected) const BoxShadow(blurRadius: 5, color: Colors.black26)], ), child: isSelected ? const Icon(Icons.check, color: Colors.white) : null, ), ); }).toList(), ), ], ), ), ), const SizedBox(height: 20), // 3. 개발자 옵션 (디버그 로그) _buildSectionTitle("개발자 옵션"), Card( child: SwitchListTile( title: const Text("디버그 로그 표시"), subtitle: const Text("로비 화면 하단에 네트워크 로그를 표시합니다."), value: _settings.isShowDebugLog, onChanged: (val) => _settings.toggleDebugLog(val), ), ), const SizedBox(height: 20), // [추가] 4. 정보 섹션 (라이선스) _buildSectionTitle("정보"), Card( child: ListTile( leading: const Icon(Icons.description_outlined), title: const Text("오픈소스 라이선스"), subtitle: const Text("앱에 사용된 라이브러리 정보"), trailing: const Icon(Icons.arrow_forward_ios, size: 16, color: Colors.grey), onTap: () { // 플러터 내장 라이선스 페이지 호출 showLicensePage( context: context, applicationName: "PlayWith", applicationVersion: "1.0.0", // applicationIcon: Image.asset('assets/icon.png', width: 50), // 아이콘이 있다면 주석 해제 ); }, ), ), const SizedBox(height: 40), // [추가] 하단 카피라이트 & 링크 GestureDetector( onTap: _launchHomepage, child: Column( children: const [ Text( "© 2025 lunaticbum. All rights reserved.", style: TextStyle(color: Colors.grey, fontSize: 12), ), SizedBox(height: 4), Text( "https://lunaticbum.kr", // 보여줄 텍스트 style: TextStyle( color: Colors.blueAccent, fontSize: 12, decoration: TextDecoration.underline ), ), ], ), ), const SizedBox(height: 30), ], ); }, ), ); } Widget _buildSectionTitle(String title) { return Padding( padding: const EdgeInsets.only(left: 8, bottom: 8), child: Text(title, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.grey)), ); } }