1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-15 14:47:18 +08:00

Merge pull request #12869 from EVAST9919/sidebar

Add sidebar to news overlay
This commit is contained in:
Dean Herbert 2021-05-21 16:21:18 +09:00 committed by GitHub
commit 1c560a9490
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 188 additions and 61 deletions

View File

@ -8,10 +8,12 @@ namespace osu.Game.Online.API.Requests
{ {
public class GetNewsRequest : APIRequest<GetNewsResponse> public class GetNewsRequest : APIRequest<GetNewsResponse>
{ {
private readonly int? year;
private readonly Cursor cursor; private readonly Cursor cursor;
public GetNewsRequest(Cursor cursor = null) public GetNewsRequest(int? year = null, Cursor cursor = null)
{ {
this.year = year;
this.cursor = cursor; this.cursor = cursor;
} }
@ -19,6 +21,10 @@ namespace osu.Game.Online.API.Requests
{ {
var req = base.CreateWebRequest(); var req = base.CreateWebRequest();
req.AddCursor(cursor); req.AddCursor(cursor);
if (year.HasValue)
req.AddParameter("year", year.Value.ToString());
return req; return req;
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -9,12 +10,18 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
namespace osu.Game.Overlays.News.Displays namespace osu.Game.Overlays.News.Displays
{ {
public class FrontPageDisplay : CompositeDrawable /// <summary>
/// Lists articles in a vertical flow for a specified year.
/// </summary>
public class ArticleListing : CompositeDrawable
{ {
public Action<APINewsSidebar> SidebarMetadataUpdated;
[Resolved] [Resolved]
private IAPIProvider api { get; set; } private IAPIProvider api { get; set; }
@ -24,6 +31,17 @@ namespace osu.Game.Overlays.News.Displays
private GetNewsRequest request; private GetNewsRequest request;
private Cursor lastCursor; private Cursor lastCursor;
private readonly int? year;
/// <summary>
/// Instantiate a listing for the specified year.
/// </summary>
/// <param name="year">The year to load articles from. If null, will show the most recent articles.</param>
public ArticleListing(int? year = null)
{
this.year = year;
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -74,7 +92,7 @@ namespace osu.Game.Overlays.News.Displays
{ {
request?.Cancel(); request?.Cancel();
request = new GetNewsRequest(lastCursor); request = new GetNewsRequest(year, lastCursor);
request.Success += response => Schedule(() => onSuccess(response)); request.Success += response => Schedule(() => onSuccess(response));
api.PerformAsync(request); api.PerformAsync(request);
} }
@ -85,22 +103,19 @@ namespace osu.Game.Overlays.News.Displays
{ {
cancellationToken?.Cancel(); cancellationToken?.Cancel();
// only needs to be updated on the initial load, as the content won't change during pagination.
if (lastCursor == null)
SidebarMetadataUpdated?.Invoke(response.SidebarMetadata);
// store cursor for next pagination request.
lastCursor = response.Cursor; lastCursor = response.Cursor;
var flow = new FillFlowContainer<NewsCard> LoadComponentsAsync(response.NewsPosts.Select(p => new NewsCard(p)).ToList(), loaded =>
{ {
RelativeSizeAxes = Axes.X, content.AddRange(loaded);
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.IsLoading = false;
showMore.Alpha = lastCursor == null ? 0 : 1; showMore.Alpha = response.Cursor != null ? 1 : 0;
}, (cancellationToken = new CancellationTokenSource()).Token); }, (cancellationToken = new CancellationTokenSource()).Token);
} }

View File

@ -19,13 +19,18 @@ namespace osu.Game.Overlays.News
{ {
TabControl.AddItem(front_page_string); TabControl.AddItem(front_page_string);
article.BindValueChanged(onArticleChanged, true);
}
protected override void LoadComplete()
{
base.LoadComplete();
Current.BindValueChanged(e => Current.BindValueChanged(e =>
{ {
if (e.NewValue == front_page_string) if (e.NewValue == front_page_string)
ShowFrontPage?.Invoke(); ShowFrontPage?.Invoke();
}); });
article.BindValueChanged(onArticleChanged, true);
} }
public void SetFrontPage() => article.Value = null; public void SetFrontPage() => article.Value = null;

View File

@ -9,6 +9,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osuTK; using osuTK;
using System.Linq; using System.Linq;
using osu.Game.Graphics.Containers;
namespace osu.Game.Overlays.News.Sidebar namespace osu.Game.Overlays.News.Sidebar
{ {
@ -31,30 +32,55 @@ namespace osu.Game.Overlays.News.Sidebar
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4 Colour = colourProvider.Background4
}, },
new Box
{
RelativeSizeAxes = Axes.Y,
Width = OsuScrollContainer.SCROLL_BAR_HEIGHT,
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Colour = colourProvider.Background3,
Alpha = 0.5f
},
new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding Padding = new MarginPadding { Right = -3 }, // Compensate for scrollbar margin
Child = new OsuScrollContainer
{ {
Vertical = 20, RelativeSizeAxes = Axes.Both,
Left = 50, Child = new Container
Right = 30
},
Child = new FillFlowContainer
{
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{ {
new YearsPanel(), RelativeSizeAxes = Axes.X,
monthsFlow = new FillFlowContainer<MonthSection> AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Right = 3 }, // Addeded 3px back
Child = new Container
{ {
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0, 10) Padding = new MarginPadding
{
Vertical = 20,
Left = 50,
Right = 30
},
Child = new FillFlowContainer
{
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0, 20),
Children = new Drawable[]
{
new YearsPanel(),
monthsFlow = new FillFlowContainer<MonthSection>
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10)
}
}
}
} }
} }
} }

View File

@ -81,6 +81,9 @@ namespace osu.Game.Overlays.News.Sidebar
{ {
public int Year { get; } public int Year { get; }
[Resolved(canBeNull: true)]
private NewsOverlay overlay { get; set; }
private readonly bool isCurrent; private readonly bool isCurrent;
public YearButton(int year, bool isCurrent) public YearButton(int year, bool isCurrent)
@ -106,7 +109,11 @@ namespace osu.Game.Overlays.News.Sidebar
{ {
IdleColour = isCurrent ? Color4.White : colourProvider.Light2; IdleColour = isCurrent ? Color4.White : colourProvider.Light2;
HoverColour = isCurrent ? Color4.White : colourProvider.Light1; HoverColour = isCurrent ? Color4.White : colourProvider.Light1;
Action = () => { }; // Avoid button being disabled since there's no proper action assigned. Action = () =>
{
if (!isCurrent)
overlay?.ShowYear(Year);
};
} }
} }
} }

View File

@ -1,11 +1,14 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Threading; using System.Threading;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Overlays.News; using osu.Game.Overlays.News;
using osu.Game.Overlays.News.Displays; using osu.Game.Overlays.News.Displays;
using osu.Game.Overlays.News.Sidebar;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
@ -13,9 +16,48 @@ namespace osu.Game.Overlays
{ {
private readonly Bindable<string> article = new Bindable<string>(null); private readonly Bindable<string> article = new Bindable<string>(null);
private readonly Container sidebarContainer;
private readonly NewsSidebar sidebar;
private readonly Container content;
private CancellationTokenSource cancellationToken;
private bool displayUpdateRequired = true;
public NewsOverlay() public NewsOverlay()
: base(OverlayColourScheme.Purple, false) : base(OverlayColourScheme.Purple, false)
{ {
Child = new GridContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize)
},
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
new Dimension()
},
Content = new[]
{
new Drawable[]
{
sidebarContainer = new Container
{
AutoSizeAxes = Axes.X,
Child = sidebar = new NewsSidebar()
},
content = new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
}
}
}
};
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -26,12 +68,7 @@ namespace osu.Game.Overlays
article.BindValueChanged(onArticleChanged); article.BindValueChanged(onArticleChanged);
} }
protected override NewsHeader CreateHeader() => new NewsHeader protected override NewsHeader CreateHeader() => new NewsHeader { ShowFrontPage = ShowFrontPage };
{
ShowFrontPage = ShowFrontPage
};
private bool displayUpdateRequired = true;
protected override void PopIn() protected override void PopIn()
{ {
@ -56,38 +93,69 @@ namespace osu.Game.Overlays
Show(); Show();
} }
public void ShowYear(int year)
{
loadFrontPage(year);
Show();
}
public void ShowArticle(string slug) public void ShowArticle(string slug)
{ {
article.Value = slug; article.Value = slug;
Show(); 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) protected void LoadDisplay(Drawable display)
{ {
ScrollFlow.ScrollToStart(); ScrollFlow.ScrollToStart();
LoadComponentAsync(display, loaded => LoadComponentAsync(display, loaded => content.Child = loaded, (cancellationToken = new CancellationTokenSource()).Token);
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
sidebarContainer.Height = DrawHeight;
sidebarContainer.Y = Math.Clamp(ScrollFlow.Current - Header.DrawHeight, 0, Math.Max(ScrollFlow.ScrollContent.DrawHeight - DrawHeight - Header.DrawHeight, 0));
}
private void onArticleChanged(ValueChangedEvent<string> article)
{
if (article.NewValue == null)
loadFrontPage();
else
loadArticle(article.NewValue);
}
private void loadFrontPage(int? year = null)
{
beginLoading();
Header.SetFrontPage();
var page = new ArticleListing(year);
page.SidebarMetadataUpdated += metadata => Schedule(() =>
{ {
Child = loaded; sidebar.Metadata.Value = metadata;
Loading.Hide(); Loading.Hide();
}, (cancellationToken = new CancellationTokenSource()).Token); });
LoadDisplay(page);
}
private void loadArticle(string article)
{
beginLoading();
Header.SetArticle(article);
// Temporary, should be handled by ArticleDisplay later
LoadDisplay(Empty());
Loading.Hide();
}
private void beginLoading()
{
cancellationToken?.Cancel();
Loading.Show();
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)