diff --git a/osu.Game.Tournament/SaveChangesOverlay.cs b/osu.Game.Tournament/SaveChangesOverlay.cs new file mode 100644 index 0000000000..b5e08fc005 --- /dev/null +++ b/osu.Game.Tournament/SaveChangesOverlay.cs @@ -0,0 +1,101 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Tournament +{ + internal class SaveChangesOverlay : CompositeDrawable + { + [Resolved] + private TournamentGame tournamentGame { get; set; } = null!; + + private string? lastSerialisedLadder; + private readonly TourneyButton saveChangesButton; + + public SaveChangesOverlay() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new Container + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Position = new Vector2(5), + CornerRadius = 10, + Masking = true, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.2f), + RelativeSizeAxes = Axes.Both, + }, + saveChangesButton = new TourneyButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Padding = new MarginPadding + { + Top = 10, + Left = 10, + }, + Margin = new MarginPadding + { + Right = 10, + Bottom = 10, + }, + Action = saveChanges, + // Enabled = { Value = false }, + }, + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + scheduleNextCheck(); + } + + private async Task checkForChanges() + { + string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder()); + + // If a save hasn't been triggered by the user yet, populate the initial value + lastSerialisedLadder ??= serialisedLadder; + + if (lastSerialisedLadder != serialisedLadder && !saveChangesButton.Enabled.Value) + { + saveChangesButton.Enabled.Value = true; + saveChangesButton.Background + .FadeColour(saveChangesButton.BackgroundColour.Lighten(0.5f), 500, Easing.In).Then() + .FadeColour(saveChangesButton.BackgroundColour, 500, Easing.Out) + .Loop(); + } + + scheduleNextCheck(); + } + + private void scheduleNextCheck() => Scheduler.AddDelayed(() => checkForChanges().FireAndForget(), 1000); + + private void saveChanges() + { + tournamentGame.SaveChanges(); + lastSerialisedLadder = tournamentGame.GetSerialisedLadder(); + + saveChangesButton.Enabled.Value = false; + saveChangesButton.Background.FadeColour(saveChangesButton.BackgroundColour, 500); + } + } +} diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 537fbfc038..7d67bfa759 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -11,8 +11,6 @@ using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Logging; using osu.Framework.Platform; @@ -20,11 +18,11 @@ using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Models; -using osuTK; using osuTK.Graphics; namespace osu.Game.Tournament { + [Cached] public class TournamentGame : TournamentGameBase { public static ColourInfo GetTeamColour(TeamColour teamColour) => teamColour == TeamColour.Red ? COLOUR_RED : COLOUR_BLUE; @@ -78,40 +76,9 @@ namespace osu.Game.Tournament LoadComponentsAsync(new[] { - new Container + new SaveChangesOverlay { - CornerRadius = 10, Depth = float.MinValue, - Position = new Vector2(5), - Masking = true, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Children = new Drawable[] - { - new Box - { - Colour = OsuColour.Gray(0.2f), - RelativeSizeAxes = Axes.Both, - }, - new TourneyButton - { - Text = "Save Changes", - Width = 140, - Height = 50, - Padding = new MarginPadding - { - Top = 10, - Left = 10, - }, - Margin = new MarginPadding - { - Right = 10, - Bottom = 10, - }, - Action = SaveChanges, - }, - } }, heightWarning = new WarningBox("Please make the window wider") { diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 75c9f17d4c..f2a35ea5b3 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -295,7 +295,7 @@ namespace osu.Game.Tournament } } - protected virtual void SaveChanges() + public void SaveChanges() { if (!bracketLoadTaskCompletionSource.Task.IsCompletedSuccessfully) { @@ -311,7 +311,16 @@ namespace osu.Game.Tournament .ToList(); // Serialise before opening stream for writing, so if there's a failure it will leave the file in the previous state. - string serialisedLadder = JsonConvert.SerializeObject(ladder, + string serialisedLadder = GetSerialisedLadder(); + + using (var stream = storage.CreateFileSafely(BRACKET_FILENAME)) + using (var sw = new StreamWriter(stream)) + sw.Write(serialisedLadder); + } + + public string GetSerialisedLadder() + { + return JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { Formatting = Formatting.Indented, @@ -319,10 +328,6 @@ namespace osu.Game.Tournament DefaultValueHandling = DefaultValueHandling.Ignore, Converters = new JsonConverter[] { new JsonPointConverter() } }); - - using (var stream = storage.CreateFileSafely(BRACKET_FILENAME)) - using (var sw = new StreamWriter(stream)) - sw.Write(serialisedLadder); } protected override UserInputManager CreateUserInputManager() => new TournamentInputManager(); diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs index f5a82771f5..f1b14df783 100644 --- a/osu.Game.Tournament/TourneyButton.cs +++ b/osu.Game.Tournament/TourneyButton.cs @@ -3,12 +3,15 @@ #nullable disable +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; namespace osu.Game.Tournament { public class TourneyButton : OsuButton { + public new Box Background => base.Background; + public TourneyButton() : base(null) {