From 74a159d534357da9fd4f98a6bc352994abb24f0c Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Fri, 26 Dec 2025 16:12:29 +0900 Subject: [PATCH] =?UTF-8?q?fix(new-character):=20=EC=BA=90=EB=A6=AD?= =?UTF-8?q?=ED=84=B0=20=EC=83=9D=EC=84=B1=20=ED=99=94=EB=A9=B4=20UX=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 굴리기 버튼 연속 클릭 방지 (100ms 딜레이) - 스크롤 애니메이션 대신 jumpTo 사용 (WASM 안정성) - Row를 Wrap으로 변경하여 버튼 레이아웃 개선 --- .../new_character/new_character_screen.dart | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/src/features/new_character/new_character_screen.dart b/lib/src/features/new_character/new_character_screen.dart index a1de027..6a8f5ef 100644 --- a/lib/src/features/new_character/new_character_screen.dart +++ b/lib/src/features/new_character/new_character_screen.dart @@ -61,6 +61,9 @@ class _NewCharacterScreenState extends State { // 테스트 모드 (웹에서 모바일 캐로셀 레이아웃 활성화) bool _testModeEnabled = false; + // 굴리기 버튼 연속 클릭 방지 + bool _isRolling = false; + @override void initState() { super.initState(); @@ -96,23 +99,22 @@ class _NewCharacterScreenState extends State { const itemHeight = 48.0; WidgetsBinding.instance.addPostFrameCallback((_) { + if (!mounted) return; + + // 스크롤 애니메이션 대신 즉시 점프 (WASM 모드 안정성) if (_raceScrollController.hasClients) { final raceOffset = _selectedRaceIndex * itemHeight; - _raceScrollController.animateTo( + _raceScrollController.jumpTo( raceOffset.clamp(0.0, _raceScrollController.position.maxScrollExtent), - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, ); } if (_klassScrollController.hasClients) { final klassOffset = _selectedKlassIndex * itemHeight; - _klassScrollController.animateTo( + _klassScrollController.jumpTo( klassOffset.clamp( 0.0, _klassScrollController.position.maxScrollExtent, ), - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, ); } }); @@ -134,6 +136,10 @@ class _NewCharacterScreenState extends State { /// Re-Roll 버튼 클릭 /// 원본 NewGuy.pas RerollClick: 스탯, 종족, 클래스 모두 랜덤화 void _onReroll() { + // 연속 클릭 방지 + if (_isRolling) return; + _isRolling = true; + // 현재 시드를 이력에 저장 _rollHistory.insert(0, _currentSeed); @@ -156,6 +162,11 @@ class _NewCharacterScreenState extends State { // 선택된 종족/직업으로 스크롤 _scrollToSelectedItems(); + + // 짧은 딜레이 후 다시 클릭 가능 + Future.delayed(const Duration(milliseconds: 100), () { + if (mounted) _isRolling = false; + }); } /// Unroll 버튼 클릭 (이전 롤로 복원) @@ -401,8 +412,10 @@ class _NewCharacterScreenState extends State { const SizedBox(height: 12), // Roll 버튼들 - Row( - mainAxisAlignment: MainAxisAlignment.center, + Wrap( + alignment: WrapAlignment.center, + spacing: 16, + runSpacing: 8, children: [ OutlinedButton.icon( onPressed: _onUnroll, @@ -412,7 +425,6 @@ class _NewCharacterScreenState extends State { foregroundColor: _rollHistory.isEmpty ? Colors.grey : null, ), ), - const SizedBox(width: 16), FilledButton.icon( onPressed: _onReroll, icon: const Icon(Icons.casino),