post a notification instead a screen

This commit is contained in:
cdwcgt 2023-09-04 16:17:21 +09:00
parent dfecddbf5d
commit 58844092d6
No known key found for this signature in database
GPG Key ID: 144396D01095C3A2
6 changed files with 169 additions and 220 deletions

View File

@ -1,13 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using System.Net;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Screens.Import;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Online
@ -24,6 +26,12 @@ namespace osu.Game.Tests.Visual.Online
OnlineBeatmapSetID = 173612,
BeatmapSet = new APIBeatmapSet
{
Title = "FREEDOM Dive",
Artist = "xi",
Covers = new BeatmapSetOnlineCovers
{
Card = "https://assets.ppy.sh/beatmaps/173612/covers/card@2x.jpg"
},
OnlineID = 173612
}
};
@ -40,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online
}
});
AddUntilStep("Replay missing screen show", () => Game.ScreenStack.CurrentScreen.GetType() == typeof(ReplayMissingBeatmapScreen));
AddUntilStep("Replay missing notification show", () => Game.Notifications.ChildrenOfType<MissingBeatmapNotification>().Any());
}
[Test]
@ -58,7 +66,7 @@ namespace osu.Game.Tests.Visual.Online
}
});
AddUntilStep("Replay missing screen not show", () => Game.ScreenStack.CurrentScreen.GetType() != typeof(ReplayMissingBeatmapScreen));
AddUntilStep("Replay missing notification not show", () => !Game.Notifications.ChildrenOfType<MissingBeatmapNotification>().Any());
}
private void setupBeatmapResponse(APIBeatmap b)

View File

@ -0,0 +1,157 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.IO;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Scoring;
using osuTK.Graphics;
namespace osu.Game.Database
{
public partial class MissingBeatmapNotification : ProgressNotification
{
[Resolved]
private BeatmapModelDownloader beatmapDownloader { get; set; } = null!;
[Resolved]
private ScoreManager scoreManager { get; set; } = null!;
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
[Resolved]
private BeatmapSetOverlay? beatmapSetOverlay { get; set; }
private Container beatmapPanelContainer = null!;
private readonly MemoryStream scoreStream;
private readonly APIBeatmapSet beatmapSetInfo;
private BeatmapDownloadTracker? downloadTracker;
private Bindable<bool> autodownloadConfig = null!;
public MissingBeatmapNotification(APIBeatmap beatmap, MemoryStream scoreStream)
{
beatmapSetInfo = beatmap.BeatmapSet!;
this.scoreStream = scoreStream;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, OsuConfigManager config)
{
autodownloadConfig = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating);
Text = "You do not have the required beatmap for this replay";
Content.Add(beatmapPanelContainer = new ClickableContainer
{
RelativeSizeAxes = Axes.X,
Height = 70,
Anchor = Anchor.CentreLeft,
Origin = Anchor.TopLeft,
Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSetInfo.OnlineID)
});
}
protected override void LoadComplete()
{
base.LoadComplete();
downloadTracker = new BeatmapDownloadTracker(beatmapSetInfo);
downloadTracker.State.BindValueChanged(downloadStatusChanged, true);
beatmapPanelContainer.Clear();
beatmapPanelContainer.Child = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 4,
Children = new Drawable[]
{
downloadTracker,
new DelayedLoadWrapper(() => new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.Card)
{
OnlineInfo = beatmapSetInfo,
RelativeSizeAxes = Axes.Both
})
{
RelativeSizeAxes = Axes.Both
},
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
Alpha = 0.4f
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Padding = new MarginPadding
{
Left = 10f,
Top = 5f
},
Children = new Drawable[]
{
new TruncatingSpriteText
{
Text = beatmapSetInfo.Title,
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
RelativeSizeAxes = Axes.X,
},
new TruncatingSpriteText
{
Text = beatmapSetInfo.Artist,
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12, italics: true),
RelativeSizeAxes = Axes.X,
}
}
},
new DownloadButton
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Width = 50,
Height = 30,
Margin = new MarginPadding
{
Bottom = 1f
},
Action = () => beatmapDownloader.Download(beatmapSetInfo),
State = { BindTarget = downloadTracker.State }
}
}
};
if (autodownloadConfig.Value)
beatmapDownloader.Download(beatmapSetInfo);
}
private void downloadStatusChanged(ValueChangedEvent<DownloadState> status)
{
if (status.NewValue != DownloadState.LocallyAvailable)
return;
var importTask = new ImportTask(scoreStream, "score.osr");
scoreManager.Import(this, new[] { importTask });
}
}
}

View File

@ -854,8 +854,6 @@ namespace osu.Game
MultiplayerClient.PostNotification = n => Notifications.Post(n);
ScoreManager.Performer = this;
// make config aware of how to lookup skins for on-screen display purposes.
// if this becomes a more common thing, tracked settings should be reconsidered to allow local DI.
LocalConfig.LookupSkinName = id => SkinManager.Query(s => s.ID == id)?.ToString() ?? "Unknown";

View File

@ -10,7 +10,6 @@ using System.Threading;
using Newtonsoft.Json;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.IO.Archives;
@ -21,8 +20,6 @@ using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens;
using osu.Game.Screens.Import;
using Realms;
namespace osu.Game.Scoring
@ -31,8 +28,6 @@ namespace osu.Game.Scoring
{
public override IEnumerable<string> HandledExtensions => new[] { ".osr" };
public IPerformFromScreenRunner? Performer { get; set; }
protected override string[] HashableFileTypes => new[] { ".osr" };
private readonly RulesetStore rulesets;
@ -69,9 +64,6 @@ namespace osu.Game.Scoring
private void onMissingBeatmap(LegacyScoreDecoder.BeatmapNotFoundException e, ArchiveReader archive, string name)
{
if (Performer == null)
return;
var stream = new MemoryStream();
// stream will close after exception throw, so fetch the stream again.
@ -87,7 +79,7 @@ namespace osu.Game.Scoring
req.Success += res =>
{
Performer.PerformFromScreen(screen => screen.Push(new ReplayMissingBeatmapScreen(res, stream)));
PostNotification?.Invoke(new MissingBeatmapNotification(res, stream));
};
api.Queue(req);

View File

@ -21,7 +21,6 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Scoring;
using osu.Game.Online.API;
using osu.Game.Scoring.Legacy;
using osu.Game.Screens;
namespace osu.Game.Scoring
{
@ -31,12 +30,6 @@ namespace osu.Game.Scoring
private readonly ScoreImporter scoreImporter;
private readonly LegacyScoreExporter scoreExporter;
[CanBeNull]
public IPerformFromScreenRunner Performer
{
set => scoreImporter.Performer = value;
}
public override bool PauseImports
{
get => base.PauseImports;

View File

@ -1,199 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables.Cards;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Settings;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osuTK;
using Realms;
namespace osu.Game.Screens.Import
{
[Cached(typeof(IPreviewTrackOwner))]
public partial class ReplayMissingBeatmapScreen : OsuScreen, IPreviewTrackOwner
{
[Resolved]
private BeatmapModelDownloader beatmapDownloader { get; set; } = null!;
[Resolved]
private ScoreManager scoreManager { get; set; } = null!;
[Resolved]
private RealmAccess realm { get; set; } = null!;
private IDisposable? realmSubscription;
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
[Resolved]
private INotificationOverlay? notificationOverlay { get; set; }
private Container beatmapPanelContainer = null!;
private ReplayDownloadButton replayDownloadButton = null!;
private SettingsCheckbox automaticDownload = null!;
private readonly MemoryStream scoreStream;
private readonly APIBeatmapSet beatmapSetInfo;
public ReplayMissingBeatmapScreen(APIBeatmap beatmap, MemoryStream scoreStream)
{
beatmapSetInfo = beatmap.BeatmapSet!;
this.scoreStream = scoreStream;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, OsuConfigManager config)
{
InternalChildren = new Drawable[]
{
new Container
{
Masking = true,
CornerRadius = 20,
AutoSizeAxes = Axes.Both,
AutoSizeDuration = 500,
AutoSizeEasing = Easing.OutQuint,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new Box
{
Colour = colours.Gray5,
RelativeSizeAxes = Axes.Both,
},
new FillFlowContainer
{
Margin = new MarginPadding(20),
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Spacing = new Vector2(15),
Children = new Drawable[]
{
new OsuSpriteText
{
Text = "Beatmap info",
Font = OsuFont.Default.With(size: 30),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Spacing = new Vector2(15),
Children = new Drawable[]
{
beatmapPanelContainer = new Container
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
}
},
automaticDownload = new SettingsCheckbox
{
LabelText = "Automatically download beatmaps",
Current = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadWhenSpectating),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
replayDownloadButton = new ReplayDownloadButton(new ScoreInfo())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
}
}
}
},
};
}
protected override void LoadComplete()
{
base.LoadComplete();
updateStatus();
realmSubscription = realm.RegisterForNotifications(
realm => realm.All<BeatmapSetInfo>().Where(s => !s.DeletePending), beatmapsChanged);
}
private void updateStatus()
{
beatmapPanelContainer.Clear();
beatmapPanelContainer.Child = new BeatmapCardNormal(beatmapSetInfo, allowExpansion: false);
checkForAutomaticDownload(beatmapSetInfo);
}
private void checkForAutomaticDownload(APIBeatmapSet beatmap)
{
if (!automaticDownload.Current.Value)
return;
beatmapDownloader.Download(beatmap);
}
private void beatmapsChanged(IRealmCollection<BeatmapSetInfo> sender, ChangeSet? changes)
{
if (changes?.InsertedIndices == null) return;
if (!scoreStream.CanRead) return;
if (sender.Any(b => b.OnlineID == beatmapSetInfo.OnlineID))
{
var progressNotification = new ImportProgressNotification();
var importTask = new ImportTask(scoreStream, "score.osr");
scoreManager.Import(progressNotification, new[] { importTask })
.ContinueWith(s =>
{
s.GetResultSafely<IEnumerable<Live<ScoreInfo>>>().FirstOrDefault()?.PerformRead(score =>
{
Guid scoreid = score.ID;
Scheduler.Add(() =>
{
replayDownloadButton.Score.Value = realm.Realm.Find<ScoreInfo>(scoreid) ?? new ScoreInfo();
});
});
});
notificationOverlay?.Post(progressNotification);
realmSubscription?.Dispose();
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
realmSubscription?.Dispose();
}
}
}