diff --git a/Agent/Task/TASK-0006.md b/Agent/Task/TASK-0006.md index bc8697f..36b5eae 100644 --- a/Agent/Task/TASK-0006.md +++ b/Agent/Task/TASK-0006.md @@ -1,5 +1,9 @@ # TASK-0006: MenuState и Restart +## Статус + +Ready + ## Цель Реализовать меню с кнопкой `Restart`, которое завершает `MenuState` и возвращает flow к загрузке. diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 7e6ee56..04d52cf 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -381,6 +381,7 @@ GameObject: m_Component: - component: {fileID: 1000000302} - component: {fileID: 1000000303} + - component: {fileID: 1000000304} m_Layer: 0 m_Name: MenuView m_TagString: Untagged @@ -414,3 +415,48 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b3333333333333333333333333333333, type: 3} m_Name: m_EditorClassIdentifier: + k__BackingField: {fileID: 1000000304} +--- !u!114 &1000000304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1000000301} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_PressedColor: {r: 0.69803923, g: 0.69803923, b: 0.69803923, a: 1} + m_SelectedColor: {r: 0.88235295, g: 0.88235295, b: 0.88235295, a: 1} + m_DisabledColor: {r: 0.52156866, g: 0.52156866, b: 0.52156866, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 0} + m_OnClick: + m_PersistentCalls: + m_Calls: [] diff --git a/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs index f6194af..a23173c 100644 --- a/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs +++ b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs @@ -17,7 +17,9 @@ namespace QuizPleaseTest.Boot.Flow public void RequestRestart() { - _restartCompletionSource?.TrySetResult(); + UniTaskCompletionSource restartCompletionSource = _restartCompletionSource; + _restartCompletionSource = null; + restartCompletionSource?.TrySetResult(); } } } diff --git a/Assets/Scripts/Boot/States/MenuState.cs b/Assets/Scripts/Boot/States/MenuState.cs index 509b985..5e1f920 100644 --- a/Assets/Scripts/Boot/States/MenuState.cs +++ b/Assets/Scripts/Boot/States/MenuState.cs @@ -1,3 +1,4 @@ +using System; using System.Threading; using Cysharp.Threading.Tasks; using QuizPleaseTest.Boot.Flow; @@ -19,9 +20,18 @@ namespace QuizPleaseTest.Boot.States public async UniTask EnterAsync(CancellationToken ct) { - _view.Bind(new MenuUIViewModel()); + _view.Bind(new MenuUIViewModel(_restartSignal)); _view.Initialize(); - await _restartSignal.WaitAsync(ct); + + try + { + await _restartSignal.WaitAsync(ct); + } + catch (OperationCanceledException) when (ct.IsCancellationRequested) + { + _view.Release(); + throw; + } } public UniTask ExitAsync(CancellationToken ct) diff --git a/Assets/Scripts/Boot/UI/MenuUIView.cs b/Assets/Scripts/Boot/UI/MenuUIView.cs index 530bf4a..8e85ed6 100644 --- a/Assets/Scripts/Boot/UI/MenuUIView.cs +++ b/Assets/Scripts/Boot/UI/MenuUIView.cs @@ -1,8 +1,39 @@ using QuizPleaseTest.Common.UI; +using UnityEngine; +using UnityEngine.UI; namespace QuizPleaseTest.Boot.UI { public class MenuUIView : UIView { + [field: SerializeField] public Button RestartButton { get; private set; } + + public override void Initialize() + { + base.Initialize(); + + if (RestartButton == null) + { + return; + } + + RestartButton.onClick.RemoveListener(OnRestartClicked); + RestartButton.onClick.AddListener(OnRestartClicked); + } + + public override void Release() + { + if (RestartButton != null) + { + RestartButton.onClick.RemoveListener(OnRestartClicked); + } + + base.Release(); + } + + private void OnRestartClicked() + { + ViewModel.Restart(); + } } } diff --git a/Assets/Scripts/Boot/UI/MenuUIViewModel.cs b/Assets/Scripts/Boot/UI/MenuUIViewModel.cs index 1bd8eb7..71bcf7e 100644 --- a/Assets/Scripts/Boot/UI/MenuUIViewModel.cs +++ b/Assets/Scripts/Boot/UI/MenuUIViewModel.cs @@ -1,8 +1,21 @@ +using System; +using QuizPleaseTest.Boot.Flow; using QuizPleaseTest.Common.UI; namespace QuizPleaseTest.Boot.UI { public class MenuUIViewModel : IUIViewModel { + private readonly IMenuRestartSignal _restartSignal; + + public MenuUIViewModel(IMenuRestartSignal restartSignal) + { + _restartSignal = restartSignal ?? throw new ArgumentNullException(nameof(restartSignal)); + } + + public void Restart() + { + _restartSignal.RequestRestart(); + } } }