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:
commit
138afea431
@ -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",
|
||||
|
53
osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs
Normal file
53
osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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: &)",
|
||||
Preview = "boom (HTML entity: &)",
|
||||
Author = "user (HTML entity: &)",
|
||||
FirstImage = "https://assets.ppy.sh/artists/88/header.jpg",
|
||||
PublishedAt = DateTimeOffset.Now
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ namespace osu.Game.Tests.Visual
|
||||
typeof(NotificationOverlay),
|
||||
typeof(BeatmapListingOverlay),
|
||||
typeof(DashboardOverlay),
|
||||
typeof(NewsOverlay),
|
||||
typeof(ChannelManager),
|
||||
typeof(ChatOverlay),
|
||||
typeof(SettingsOverlay),
|
||||
|
27
osu.Game/Online/API/Requests/GetNewsRequest.cs
Normal file
27
osu.Game/Online/API/Requests/GetNewsRequest.cs
Normal 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";
|
||||
}
|
||||
}
|
15
osu.Game/Online/API/Requests/GetNewsResponse.cs
Normal file
15
osu.Game/Online/API/Requests/GetNewsResponse.cs
Normal 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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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()
|
||||
|
114
osu.Game/Overlays/News/Displays/FrontPageDisplay.cs
Normal file
114
osu.Game/Overlays/News/Displays/FrontPageDisplay.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
AutoSizeAxes = Axes.X,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ToolbarNewsButton(),
|
||||
new ToolbarChangelogButton(),
|
||||
new ToolbarRankingsButton(),
|
||||
new ToolbarBeatmapListingButton(),
|
||||
|
22
osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs
Normal file
22
osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user