1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 01:02:55 +08:00

Merge pull request #9459 from EVAST9919/news

News overlay implementaton
This commit is contained in:
Dan Balasescu 2020-08-03 15:51:27 +09:00 committed by GitHub
commit 138afea431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 380 additions and 306 deletions

View File

@ -31,15 +31,16 @@ namespace osu.Game.Tests.Visual.Online
{
new NewsCard(new APINewsPost
{
Title = "This post has an image which starts with \"/\" and has many authors!",
Title = "This post has an image which starts with \"/\" and has many authors! (clickable)",
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
Author = "someone, someone1, someone2, someone3, someone4",
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
PublishedAt = DateTimeOffset.Now
PublishedAt = DateTimeOffset.Now,
Slug = "2020-07-16-summer-theme-park-2020-voting-open"
}),
new NewsCard(new APINewsPost
{
Title = "This post has a full-url image! (HTML entity: &)",
Title = "This post has a full-url image! (HTML entity: &) (non-clickable)",
Preview = "boom (HTML entity: &)",
Author = "user (HTML entity: &)",
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",

View File

@ -0,0 +1,53 @@
// 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 NUnit.Framework;
using osu.Game.Overlays.News;
using osu.Framework.Graphics;
using osu.Game.Overlays;
using osu.Framework.Allocation;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneNewsHeader : OsuTestScene
{
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
private TestHeader header;
[SetUp]
public void Setup() => Schedule(() =>
{
Child = header = new TestHeader
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
});
[Test]
public void TestControl()
{
AddAssert("Front page selected", () => header.Current.Value == "frontpage");
AddAssert("1 tab total", () => header.TabCount == 1);
AddStep("Set article 1", () => header.SetArticle("1"));
AddAssert("Article 1 selected", () => header.Current.Value == "1");
AddAssert("2 tabs total", () => header.TabCount == 2);
AddStep("Set article 2", () => header.SetArticle("2"));
AddAssert("Article 2 selected", () => header.Current.Value == "2");
AddAssert("2 tabs total", () => header.TabCount == 2);
AddStep("Set front page", () => header.SetFrontPage());
AddAssert("Front page selected", () => header.Current.Value == "frontpage");
AddAssert("1 tab total", () => header.TabCount == 1);
}
private class TestHeader : NewsHeader
{
public int TabCount => TabControl.Items.Count;
}
}
}

View File

@ -2,65 +2,64 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Graphics;
using NUnit.Framework;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.News;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneNewsOverlay : OsuTestScene
{
private TestNewsOverlay news;
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
protected override void LoadComplete()
private NewsOverlay news;
[SetUp]
public void SetUp() => Schedule(() => Child = news = new NewsOverlay());
[Test]
public void TestRequest()
{
base.LoadComplete();
Add(news = new TestNewsOverlay());
AddStep(@"Show", news.Show);
AddStep(@"Hide", news.Hide);
AddStep(@"Show front page", () => news.ShowFrontPage());
AddStep(@"Custom article", () => news.Current.Value = "Test Article 101");
AddStep(@"Article covers", () => news.LoadAndShowContent(new NewsCoverTest()));
setUpNewsResponse(responseExample);
AddStep("Show", () => news.Show());
AddStep("Show article", () => news.ShowArticle("article"));
}
private class TestNewsOverlay : NewsOverlay
{
public new void LoadAndShowContent(NewsContent content) => base.LoadAndShowContent(content);
}
private class NewsCoverTest : NewsContent
{
public NewsCoverTest()
private void setUpNewsResponse(GetNewsResponse r)
=> AddStep("set up response", () =>
{
Spacing = new osuTK.Vector2(0, 10);
var article = new NewsArticleCover.ArticleInfo
dummyAPI.HandleRequest = request =>
{
Author = "Ephemeral",
CoverUrl = "https://assets.ppy.sh/artists/58/header.jpg",
Time = new DateTime(2019, 12, 4),
Title = "New Featured Artist: Kurokotei"
};
if (!(request is GetNewsRequest getNewsRequest))
return;
Children = new Drawable[]
{
new NewsArticleCover(article)
{
Height = 200
},
new NewsArticleCover(article)
{
Height = 120
},
new NewsArticleCover(article)
{
RelativeSizeAxes = Axes.None,
Size = new osuTK.Vector2(400, 200),
}
getNewsRequest.TriggerSuccess(r);
};
});
private GetNewsResponse responseExample => new GetNewsResponse
{
NewsPosts = new[]
{
new APINewsPost
{
Title = "This post has an image which starts with \"/\" and has many authors!",
Preview = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
Author = "someone, someone1, someone2, someone3, someone4",
FirstImage = "/help/wiki/shared/news/banners/monthly-beatmapping-contest.png",
PublishedAt = DateTimeOffset.Now
},
new APINewsPost
{
Title = "This post has a full-url image! (HTML entity: &amp;)",
Preview = "boom (HTML entity: &amp;)",
Author = "user (HTML entity: &amp;)",
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
PublishedAt = DateTimeOffset.Now
}
}
}
};
}
}

View File

@ -44,6 +44,7 @@ namespace osu.Game.Tests.Visual
typeof(NotificationOverlay),
typeof(BeatmapListingOverlay),
typeof(DashboardOverlay),
typeof(NewsOverlay),
typeof(ChannelManager),
typeof(ChatOverlay),
typeof(SettingsOverlay),

View File

@ -0,0 +1,27 @@
// 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 osu.Framework.IO.Network;
using osu.Game.Extensions;
namespace osu.Game.Online.API.Requests
{
public class GetNewsRequest : APIRequest<GetNewsResponse>
{
private readonly Cursor cursor;
public GetNewsRequest(Cursor cursor = null)
{
this.cursor = cursor;
}
protected override WebRequest CreateWebRequest()
{
var req = base.CreateWebRequest();
req.AddCursor(cursor);
return req;
}
protected override string Target => "news";
}
}

View File

@ -0,0 +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.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class GetNewsResponse : ResponseWithCursor
{
[JsonProperty("news_posts")]
public IEnumerable<APINewsPost> NewsPosts;
}
}

View File

@ -73,6 +73,8 @@ namespace osu.Game
private DashboardOverlay dashboard;
private NewsOverlay news;
private UserProfileOverlay userProfile;
private BeatmapSetOverlay beatmapSetOverlay;
@ -632,6 +634,7 @@ namespace osu.Game
// overlay elements
loadComponentSingleFile(beatmapListing = new BeatmapListingOverlay(), overlayContent.Add, true);
loadComponentSingleFile(dashboard = new DashboardOverlay(), overlayContent.Add, true);
loadComponentSingleFile(news = new NewsOverlay(), overlayContent.Add, true);
var rankingsOverlay = loadComponentSingleFile(new RankingsOverlay(), overlayContent.Add, true);
loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true);
loadComponentSingleFile(chatOverlay = new ChatOverlay(), overlayContent.Add, true);
@ -689,7 +692,7 @@ namespace osu.Game
}
// ensure only one of these overlays are open at once.
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, dashboard, beatmapListing, changelogOverlay, rankingsOverlay };
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay };
foreach (var overlay in singleDisplayOverlays)
{

View File

@ -19,7 +19,6 @@ namespace osu.Game.Overlays
{
private CancellationTokenSource cancellationToken;
private Box background;
private Container content;
private DashboardOverlayHeader header;
private LoadingLayer loading;
@ -35,9 +34,10 @@ namespace osu.Game.Overlays
{
Children = new Drawable[]
{
background = new Box
new Box
{
RelativeSizeAxes = Axes.Both
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider.Background5
},
scrollFlow = new OverlayScrollContainer
{
@ -66,8 +66,6 @@ namespace osu.Game.Overlays
},
loading = new LoadingLayer(content),
};
background.Colour = ColourProvider.Background5;
}
protected override void LoadComplete()

View File

@ -0,0 +1,114 @@
// 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.Threading;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osuTK;
namespace osu.Game.Overlays.News.Displays
{
public class FrontPageDisplay : CompositeDrawable
{
[Resolved]
private IAPIProvider api { get; set; }
private FillFlowContainer content;
private ShowMoreButton showMore;
private GetNewsRequest request;
private Cursor lastCursor;
[BackgroundDependencyLoader]
private void load()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding
{
Vertical = 20,
Left = 30,
Right = 50
};
InternalChild = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
content = new FillFlowContainer
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10)
},
showMore = new ShowMoreButton
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Margin = new MarginPadding
{
Top = 15
},
Action = performFetch,
Alpha = 0
}
}
};
performFetch();
}
private void performFetch()
{
request?.Cancel();
request = new GetNewsRequest(lastCursor);
request.Success += response => Schedule(() => onSuccess(response));
api.PerformAsync(request);
}
private CancellationTokenSource cancellationToken;
private void onSuccess(GetNewsResponse response)
{
cancellationToken?.Cancel();
lastCursor = response.Cursor;
var flow = new FillFlowContainer<NewsCard>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = response.NewsPosts.Select(p => new NewsCard(p)).ToList()
};
LoadComponentAsync(flow, loaded =>
{
content.Add(loaded);
showMore.IsLoading = false;
showMore.Show();
}, (cancellationToken = new CancellationTokenSource()).Token);
}
protected override void Dispose(bool isDisposing)
{
request?.Cancel();
cancellationToken?.Cancel();
base.Dispose(isDisposing);
}
}
}

View File

@ -1,174 +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 osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osuTK.Graphics;
namespace osu.Game.Overlays.News
{
public class NewsArticleCover : Container
{
private const int hover_duration = 300;
private readonly Box gradient;
public NewsArticleCover(ArticleInfo info)
{
RelativeSizeAxes = Axes.X;
Masking = true;
CornerRadius = 4;
NewsBackground bg;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.1f))
},
new DelayedLoadWrapper(bg = new NewsBackground(info.CoverUrl)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fill,
Alpha = 0
})
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
},
gradient = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.7f)),
Alpha = 0
},
new DateContainer(info.Time)
{
Margin = new MarginPadding
{
Right = 20,
Top = 20,
}
},
new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding
{
Left = 25,
Bottom = 50,
},
Font = OsuFont.GetFont(Typeface.Torus, 24, FontWeight.Bold),
Text = info.Title,
},
new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Margin = new MarginPadding
{
Left = 25,
Bottom = 30,
},
Font = OsuFont.GetFont(Typeface.Torus, 16, FontWeight.Bold),
Text = "by " + info.Author
}
};
bg.OnLoadComplete += d => d.FadeIn(250, Easing.In);
}
protected override bool OnHover(HoverEvent e)
{
gradient.FadeIn(hover_duration, Easing.OutQuint);
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
base.OnHoverLost(e);
gradient.FadeOut(hover_duration, Easing.OutQuint);
}
[LongRunningLoad]
private class NewsBackground : Sprite
{
private readonly string url;
public NewsBackground(string coverUrl)
{
url = coverUrl ?? "Headers/news";
}
[BackgroundDependencyLoader]
private void load(LargeTextureStore store)
{
Texture = store.Get(url);
}
}
private class DateContainer : Container, IHasTooltip
{
private readonly DateTime date;
public DateContainer(DateTime date)
{
this.date = date;
Anchor = Anchor.TopRight;
Origin = Anchor.TopRight;
Masking = true;
CornerRadius = 4;
AutoSizeAxes = Axes.Both;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.5f),
},
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = OsuFont.GetFont(Typeface.Torus, 12, FontWeight.Bold, false, false),
Text = date.ToString("d MMM yyy").ToUpper(),
Margin = new MarginPadding
{
Vertical = 4,
Horizontal = 8,
}
}
};
}
public string TooltipText => date.ToString("dddd dd MMMM yyyy hh:mm:ss UTCz").ToUpper();
}
// fake API data struct to use for now as a skeleton for data, as there is no API struct for news article info for now
public class ArticleInfo
{
public string Title { get; set; }
public string CoverUrl { get; set; }
public DateTime Time { get; set; }
public string Author { get; set; }
}
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
@ -11,17 +12,17 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Events;
using osu.Framework.Platform;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Overlays.News
{
public class NewsCard : CompositeDrawable
public class NewsCard : OsuHoverContainer
{
[Resolved]
private OverlayColourProvider colourProvider { get; set; }
protected override IEnumerable<Drawable> EffectTargets => new[] { background };
private readonly APINewsPost post;
@ -31,24 +32,28 @@ namespace osu.Game.Overlays.News
public NewsCard(APINewsPost post)
{
this.post = post;
}
[BackgroundDependencyLoader]
private void load()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Masking = true;
CornerRadius = 6;
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider, GameHost host)
{
if (post.Slug != null)
{
TooltipText = "view in browser";
Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug);
}
NewsBackground bg;
InternalChildren = new Drawable[]
AddRange(new Drawable[]
{
background = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4
RelativeSizeAxes = Axes.Both
},
new FillFlowContainer
{
@ -104,9 +109,11 @@ namespace osu.Game.Overlays.News
}
}
}
},
new HoverClickSounds()
};
}
});
IdleColour = colourProvider.Background4;
HoverColour = colourProvider.Background3;
bg.OnLoadComplete += d => d.FadeIn(250, Easing.In);
@ -116,18 +123,6 @@ namespace osu.Game.Overlays.News
main.AddText(post.Author, t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold));
}
protected override bool OnHover(HoverEvent e)
{
background.FadeColour(colourProvider.Background3, 200, Easing.OutQuint);
return true;
}
protected override void OnHoverLost(HoverLostEvent e)
{
background.FadeColour(colourProvider.Background4, 200, Easing.OutQuint);
base.OnHoverLost(e);
}
[LongRunningLoad]
private class NewsBackground : Sprite
{
@ -193,6 +188,8 @@ namespace osu.Game.Overlays.News
}
};
}
protected override bool OnClick(ClickEvent e) => true; // Protects the NewsCard from clicks while hovering DateContainer
}
}
}

View File

@ -1,19 +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 osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Overlays.News
{
public abstract class NewsContent : FillFlowContainer
{
protected NewsContent()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Direction = FillDirection.Vertical;
Padding = new MarginPadding { Bottom = 100, Top = 20, Horizontal = 50 };
}
}
}

View File

@ -1,9 +1,9 @@
// 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 osu.Framework.Bindables;
using osu.Framework.Graphics;
using System;
namespace osu.Game.Overlays.News
{
@ -11,24 +11,28 @@ namespace osu.Game.Overlays.News
{
private const string front_page_string = "frontpage";
public readonly Bindable<string> Post = new Bindable<string>(null);
public Action ShowFrontPage;
private readonly Bindable<string> article = new Bindable<string>(null);
public NewsHeader()
{
TabControl.AddItem(front_page_string);
Current.ValueChanged += e =>
Current.BindValueChanged(e =>
{
if (e.NewValue == front_page_string)
ShowFrontPage?.Invoke();
};
});
Post.ValueChanged += showPost;
article.BindValueChanged(onArticleChanged, true);
}
private void showPost(ValueChangedEvent<string> e)
public void SetFrontPage() => article.Value = null;
public void SetArticle(string slug) => article.Value = slug;
private void onArticleChanged(ValueChangedEvent<string> e)
{
if (e.OldValue != null)
TabControl.RemoveItem(e.OldValue);

View File

@ -7,18 +7,20 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.News;
using osu.Game.Overlays.News.Displays;
namespace osu.Game.Overlays
{
public class NewsOverlay : FullscreenOverlay
{
private readonly Bindable<string> article = new Bindable<string>(null);
private Container content;
private LoadingLayer loading;
private NewsHeader header;
private Container<NewsContent> content;
public readonly Bindable<string> Current = new Bindable<string>(null);
private OverlayScrollContainer scrollFlow;
public NewsOverlay()
: base(OverlayColourScheme.Purple)
@ -26,18 +28,19 @@ namespace osu.Game.Overlays
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
private void load()
{
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colours.PurpleDarkAlternative
Colour = ColourProvider.Background5,
},
new OverlayScrollContainer
scrollFlow = new OverlayScrollContainer
{
RelativeSizeAxes = Axes.Both,
ScrollbarVisible = false,
Child = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
@ -49,7 +52,7 @@ namespace osu.Game.Overlays
{
ShowFrontPage = ShowFrontPage
},
content = new Container<NewsContent>
content = new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
@ -57,31 +60,60 @@ namespace osu.Game.Overlays
},
},
},
loading = new LoadingLayer(content),
};
header.Post.BindTo(Current);
Current.TriggerChange();
}
private CancellationTokenSource loadContentCancellation;
protected void LoadAndShowContent(NewsContent newContent)
protected override void LoadComplete()
{
content.FadeTo(0.2f, 300, Easing.OutQuint);
loadContentCancellation?.Cancel();
LoadComponentAsync(newContent, c =>
{
content.Child = c;
content.FadeIn(300, Easing.OutQuint);
}, (loadContentCancellation = new CancellationTokenSource()).Token);
base.LoadComplete();
article.BindValueChanged(onArticleChanged, true);
}
public void ShowFrontPage()
{
Current.Value = null;
article.Value = null;
Show();
}
public void ShowArticle(string slug)
{
article.Value = slug;
Show();
}
private CancellationTokenSource cancellationToken;
private void onArticleChanged(ValueChangedEvent<string> e)
{
cancellationToken?.Cancel();
loading.Show();
if (e.NewValue == null)
{
header.SetFrontPage();
LoadDisplay(new FrontPageDisplay());
return;
}
header.SetArticle(e.NewValue);
LoadDisplay(Empty());
}
protected void LoadDisplay(Drawable display)
{
scrollFlow.ScrollToStart();
LoadComponentAsync(display, loaded =>
{
content.Child = loaded;
loading.Hide();
}, (cancellationToken = new CancellationTokenSource()).Token);
}
protected override void Dispose(bool isDisposing)
{
cancellationToken?.Cancel();
base.Dispose(isDisposing);
}
}
}

View File

@ -69,6 +69,7 @@ namespace osu.Game.Overlays.Toolbar
AutoSizeAxes = Axes.X,
Children = new Drawable[]
{
new ToolbarNewsButton(),
new ToolbarChangelogButton(),
new ToolbarRankingsButton(),
new ToolbarBeatmapListingButton(),

View File

@ -0,0 +1,22 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
namespace osu.Game.Overlays.Toolbar
{
public class ToolbarNewsButton : ToolbarOverlayToggleButton
{
public ToolbarNewsButton()
{
Icon = FontAwesome.Solid.Newspaper;
}
[BackgroundDependencyLoader(true)]
private void load(NewsOverlay news)
{
StateContainer = news;
}
}
}