mirror of https://github.com/ppy/osu
Protect against requests to show overlays before the target overlay is ready
This commit is contained in:
parent
898520935e
commit
f038c579f0
|
@ -215,16 +215,20 @@ private void load(FrameworkConfigManager frameworkConfig)
|
|||
|
||||
private ExternalLinkOpener externalLinkOpener;
|
||||
|
||||
public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url));
|
||||
/// <summary>
|
||||
/// Handle an arbitrary URL. Displays via in-game overlays where possible.
|
||||
/// This can be called from a non-thread-safe non-game-loaded state.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to load.</param>
|
||||
public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url)));
|
||||
|
||||
/// <summary>
|
||||
/// Handle a specific <see cref="LinkDetails"/>.
|
||||
/// This can be called from a non-thread-safe non-game-loaded state.
|
||||
/// </summary>
|
||||
/// <param name="link">The link to load.</param>
|
||||
public void HandleLink(LinkDetails link)
|
||||
{
|
||||
Action showNotImplementedError = () => notifications?.Post(new SimpleNotification
|
||||
{
|
||||
Text = @"This link type is not yet supported!",
|
||||
Icon = FontAwesome.Solid.LifeRing,
|
||||
});
|
||||
|
||||
switch (link.Action)
|
||||
{
|
||||
case LinkAction.OpenBeatmap:
|
||||
|
@ -239,21 +243,17 @@ public void HandleLink(LinkDetails link)
|
|||
break;
|
||||
|
||||
case LinkAction.OpenChannel:
|
||||
try
|
||||
{
|
||||
channelManager.OpenChannel(link.Argument);
|
||||
}
|
||||
catch (ChannelNotFoundException)
|
||||
{
|
||||
Logger.Log($"The requested channel \"{link.Argument}\" does not exist");
|
||||
}
|
||||
|
||||
ShowChannel(link.Argument);
|
||||
break;
|
||||
|
||||
case LinkAction.OpenEditorTimestamp:
|
||||
case LinkAction.JoinMultiplayerMatch:
|
||||
case LinkAction.Spectate:
|
||||
showNotImplementedError.Invoke();
|
||||
waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification
|
||||
{
|
||||
Text = @"This link type is not yet supported!",
|
||||
Icon = FontAwesome.Solid.LifeRing,
|
||||
}));
|
||||
break;
|
||||
|
||||
case LinkAction.External:
|
||||
|
@ -270,31 +270,47 @@ public void HandleLink(LinkDetails link)
|
|||
}
|
||||
}
|
||||
|
||||
public void OpenUrlExternally(string url)
|
||||
public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ =>
|
||||
{
|
||||
if (url.StartsWith("/"))
|
||||
url = $"{API.Endpoint}{url}";
|
||||
|
||||
externalLinkOpener.OpenUrlExternally(url);
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Open a specific channel in chat.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel to display.</param>
|
||||
public void ShowChannel(string channel) => waitForReady(() => channelManager, _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
channelManager.OpenChannel(channel);
|
||||
}
|
||||
catch (ChannelNotFoundException)
|
||||
{
|
||||
Logger.Log($"The requested channel \"{channel}\" does not exist");
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Show a beatmap set as an overlay.
|
||||
/// </summary>
|
||||
/// <param name="setId">The set to display.</param>
|
||||
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
|
||||
public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId));
|
||||
|
||||
/// <summary>
|
||||
/// Show a user's profile as an overlay.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user to display.</param>
|
||||
public void ShowUser(long userId) => userProfile.ShowUser(userId);
|
||||
public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId));
|
||||
|
||||
/// <summary>
|
||||
/// Show a beatmap's set as an overlay, displaying the given beatmap.
|
||||
/// </summary>
|
||||
/// <param name="beatmapId">The beatmap to show.</param>
|
||||
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId);
|
||||
public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
|
||||
|
||||
/// <summary>
|
||||
/// Present a beatmap at song select immediately.
|
||||
|
@ -452,6 +468,23 @@ private void performFromMainMenu(Action action, string taskName, Type targetScre
|
|||
performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for the game (and target component) to become loaded and then run an action.
|
||||
/// </summary>
|
||||
/// <param name="retrieveInstance">A function to retrieve a (potentially not-yet-constructed) target instance.</param>
|
||||
/// <param name="action">The action to perform on the instance when load is confirmed.</param>
|
||||
/// <typeparam name="T">The type of the target instance.</typeparam>
|
||||
private void waitForReady<T>(Func<T> retrieveInstance, Action<T> action)
|
||||
where T : Drawable
|
||||
{
|
||||
var instance = retrieveInstance();
|
||||
|
||||
if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true)
|
||||
Schedule(() => waitForReady(retrieveInstance, action));
|
||||
else
|
||||
action(instance);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
|
Loading…
Reference in New Issue