From b62630ecd22c86a632584946e4ce189f257a032b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Jan 2019 21:10:34 +0900 Subject: [PATCH 01/18] Centralise download tracking logic so we can show it in multiple scenarios --- .../BeatmapSet/Buttons/DownloadButton.cs | 70 +++++++++-------- osu.Game/Overlays/Direct/DirectPanel.cs | 60 +-------------- .../Overlays/Direct/DownloadProgressBar.cs | 70 +++++++++++++++++ .../Direct/DownloadTrackingComponent.cs | 77 +++++++++++++++++++ 4 files changed, 188 insertions(+), 89 deletions(-) create mode 100644 osu.Game/Overlays/Direct/DownloadProgressBar.cs create mode 100644 osu.Game/Overlays/Direct/DownloadTrackingComponent.cs diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 8406dada44..9d9f71a7fa 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; +using osu.Game.Overlays.Direct; using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -28,44 +29,53 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Width = 120; BeatmapSetDownloader downloader; - Add(new Container + AddRange(new Drawable[] { - Depth = -1, - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 10 }, - Children = new Drawable[] + new Container { - downloader = new BeatmapSetDownloader(set, noVideo), - new FillFlowContainer + Depth = -1, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 10 }, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new[] + downloader = new BeatmapSetDownloader(set, noVideo), + new FillFlowContainer { - new OsuSpriteText + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new[] { - Text = "Download", - TextSize = 13, - Font = @"Exo2.0-Bold", - }, - new OsuSpriteText - { - Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, - TextSize = 11, - Font = @"Exo2.0-Bold", + new OsuSpriteText + { + Text = "Download", + TextSize = 13, + Font = @"Exo2.0-Bold", + }, + new OsuSpriteText + { + Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, + TextSize = 11, + Font = @"Exo2.0-Bold", + }, }, }, + new SpriteIcon + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Icon = FontAwesome.fa_download, + Size = new Vector2(16), + Margin = new MarginPadding { Right = 5 }, + }, }, - new SpriteIcon - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Icon = FontAwesome.fa_download, - Size = new Vector2(16), - Margin = new MarginPadding { Right = 5 }, - }, + }, + new DownloadProgressBar(set) + { + Depth = -2, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, }, }); diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 44556a6360..a3d144e22f 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -16,8 +16,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API.Requests; using osuTK; using osuTK.Graphics; @@ -31,8 +29,6 @@ namespace osu.Game.Overlays.Direct private Container content; - private ProgressBar progressBar; - private BeatmapManager beatmaps; private BeatmapSetOverlay beatmapSetOverlay; public PreviewTrack Preview => PlayButton.Preview; @@ -65,14 +61,10 @@ namespace osu.Game.Overlays.Direct Colour = Color4.Black.Opacity(0.3f), }; - private OsuColour colours; - [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { - this.beatmaps = beatmaps; this.beatmapSetOverlay = beatmapSetOverlay; - this.colours = colours; AddInternal(content = new Container { @@ -82,33 +74,14 @@ namespace osu.Game.Overlays.Direct Children = new[] { CreateBackground(), - progressBar = new ProgressBar + new DownloadProgressBar(SetInfo) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Height = 0, - Alpha = 0, - BackgroundColour = Color4.Black.Opacity(0.7f), - FillColour = colours.Blue, Depth = -1, }, } }); - - var downloadRequest = beatmaps.GetExistingDownload(SetInfo); - - if (downloadRequest != null) - attachDownload(downloadRequest); - - beatmaps.BeatmapDownloadBegan += attachDownload; - beatmaps.ItemAdded += setAdded; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - beatmaps.BeatmapDownloadBegan -= attachDownload; - beatmaps.ItemAdded -= setAdded; } protected override void Update() @@ -149,37 +122,6 @@ namespace osu.Game.Overlays.Direct protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo); - private void attachDownload(DownloadBeatmapSetRequest request) - { - if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID) - return; - - progressBar.FadeIn(400, Easing.OutQuint); - progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); - - progressBar.Current.Value = 0; - - request.Failure += e => - { - progressBar.Current.Value = 0; - progressBar.FadeOut(500); - }; - - request.DownloadProgressed += progress => Schedule(() => progressBar.Current.Value = progress); - - request.Success += data => - { - progressBar.Current.Value = 1; - progressBar.FillColour = colours.Yellow; - }; - } - - private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => - { - if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) - progressBar.FadeOut(500); - }); - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs new file mode 100644 index 0000000000..60632980a7 --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Direct +{ + public class DownloadProgressBar : DownloadTrackingComponent + { + private readonly ProgressBar progressBar; + + private OsuColour colours; + + public DownloadProgressBar(BeatmapSetInfo setInfo) + : base(setInfo) + { + AddInternal(progressBar = new ProgressBar + { + Height = 0, + Alpha = 0, + }); + + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours) + { + this.colours = colours; + + progressBar.FillColour = colours.Blue; + progressBar.BackgroundColour = Color4.Black.Opacity(0.7f); + } + + protected override void DownloadFailed() + { + progressBar.Current.Value = 0; + progressBar.FadeOut(500); + } + + protected override void DownloadComleted() + { + progressBar.Current.Value = 1; + progressBar.FillColour = colours.Yellow; + } + + protected override void DownloadStarted() + { + progressBar.FadeIn(400, Easing.OutQuint); + progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); + } + + protected override void BeatmapImported() + { + progressBar.FadeOut(500); + } + + protected override void ProgressChanged(float progress) + { + progressBar.Current.Value = progress; + } + } +} diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs b/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs new file mode 100644 index 0000000000..8b42832554 --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs @@ -0,0 +1,77 @@ +// Copyright (c) 2007-2019 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests; + +namespace osu.Game.Overlays.Direct +{ + public abstract class DownloadTrackingComponent : CompositeDrawable + { + private readonly BeatmapSetInfo setInfo; + private BeatmapManager beatmaps; + + protected DownloadTrackingComponent(BeatmapSetInfo beatmapSetInfo) + { + setInfo = beatmapSetInfo; + } + + #region Disposal + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + beatmaps.BeatmapDownloadBegan -= attachDownload; + beatmaps.ItemAdded -= setAdded; + } + + #endregion + + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps) + { + this.beatmaps = beatmaps; + + var downloadRequest = beatmaps.GetExistingDownload(setInfo); + + if (downloadRequest != null) + attachDownload(downloadRequest); + + beatmaps.BeatmapDownloadBegan += attachDownload; + beatmaps.ItemAdded += setAdded; + } + + private void attachDownload(DownloadBeatmapSetRequest request) + { + if (request.BeatmapSet.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) + return; + + DownloadStarted(); + + request.Failure += e => { DownloadFailed(); }; + + request.DownloadProgressed += progress => Schedule(() => ProgressChanged(progress)); + request.Success += data => { DownloadComleted(); }; + } + + protected abstract void ProgressChanged(float progress); + + protected abstract void DownloadFailed(); + + protected abstract void DownloadComleted(); + + protected abstract void BeatmapImported(); + + protected abstract void DownloadStarted(); + + private void setAdded(BeatmapSetInfo s, bool existing, bool silent) + { + if (s.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) + return; + + Schedule(BeatmapImported); + } + } +} \ No newline at end of file From 8848fa8b1b0f8065972327d8d1bafc9d8637b721 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Jan 2019 12:04:49 +0900 Subject: [PATCH 02/18] Improve UX of download buttons on beatmap set overlay --- .../BeatmapSet/Buttons/DownloadButton.cs | 49 +++++++++----- osu.Game/Overlays/BeatmapSet/Header.cs | 64 +++++++++---------- 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 9d9f71a7fa..a44e2c7fab 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -29,6 +29,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Width = 120; BeatmapSetDownloader downloader; + FillFlowContainer textSprites; + AddRange(new Drawable[] { new Container @@ -39,27 +41,14 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Children = new Drawable[] { downloader = new BeatmapSetDownloader(set, noVideo), - new FillFlowContainer + textSprites = new FillFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, + AutoSizeDuration = 500, + AutoSizeEasing = Easing.OutQuint, Direction = FillDirection.Vertical, - Children = new[] - { - new OsuSpriteText - { - Text = "Download", - TextSize = 13, - Font = @"Exo2.0-Bold", - }, - new OsuSpriteText - { - Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, - TextSize = 11, - Font = @"Exo2.0-Bold", - }, - }, }, new SpriteIcon { @@ -97,14 +86,42 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { switch (state) { + case BeatmapSetDownloader.DownloadStatus.Downloading: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Downloading...", + TextSize = 13, + Font = @"Exo2.0-Bold", + }, + }; + break; case BeatmapSetDownloader.DownloadStatus.Downloaded: this.FadeOut(200); break; case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Download", + TextSize = 13, + Font = @"Exo2.0-Bold", + }, + new OsuSpriteText + { + Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, + TextSize = 11, + Font = @"Exo2.0-Bold", + }, + }; this.FadeIn(200); break; } }; + + downloader.DownloadState.TriggerChange(); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index d353522d8d..c702c7cb87 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -28,10 +28,8 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Box tabsBg; private readonly UpdateableBeatmapSetCover cover; private readonly OsuSpriteText title, artist; - private readonly Container noVideoButtons; - private readonly FillFlowContainer videoButtons; private readonly AuthorInfo author; - private readonly Container downloadButtonsContainer; + private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; public Details Details; @@ -54,8 +52,13 @@ namespace osu.Game.Overlays.BeatmapSet } } + private BeatmapSetDownloader downloader; + private void updateDisplay() { + downloader?.Expire(); + + title.Text = BeatmapSet?.Metadata.Title ?? string.Empty; artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty; onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; @@ -66,24 +69,30 @@ namespace osu.Game.Overlays.BeatmapSet downloadButtonsContainer.FadeIn(transition_duration); favouriteButton.FadeIn(transition_duration); - if (BeatmapSet.OnlineInfo.HasVideo) + Add(downloader = new BeatmapSetDownloader(BeatmapSet)); + downloader.DownloadState.BindValueChanged(state => { - videoButtons.Children = new[] + switch (state) { - new DownloadButton(BeatmapSet), - new DownloadButton(BeatmapSet, true), - }; - - videoButtons.FadeIn(transition_duration); - noVideoButtons.FadeOut(transition_duration); - } - else - { - noVideoButtons.Child = new DownloadButton(BeatmapSet); - - noVideoButtons.FadeIn(transition_duration); - videoButtons.FadeOut(transition_duration); - } + case BeatmapSetDownloader.DownloadStatus.Downloaded: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet) + { + Width = 50, + RelativeSizeAxes = Axes.Y + }; + break; + case BeatmapSetDownloader.DownloadStatus.Downloading: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + break; + default: + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + if (BeatmapSet.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true)); + break; + } + }, true); } else { @@ -196,24 +205,11 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { favouriteButton = new FavouriteButton(), - downloadButtonsContainer = new Container + downloadButtonsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, - Children = new Drawable[] - { - noVideoButtons = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - }, - videoButtons = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Spacing = new Vector2(buttons_spacing), - Alpha = 0f, - }, - }, + Spacing = new Vector2(buttons_spacing), }, }, }, From 21e79f51b1fdef7a1cc166697f607ff87e7b20f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Jan 2019 14:28:06 +0900 Subject: [PATCH 03/18] Remove necessity of BeatmapSetDownloader --- .../Drawables/BeatmapSetDownloader.cs | 112 --------------- .../API/Requests/DownloadBeatmapSetRequest.cs | 2 +- .../BeatmapSet/Buttons/DownloadButton.cs | 123 +++++++++-------- osu.Game/Overlays/BeatmapSet/Header.cs | 127 ++++++++---------- osu.Game/Overlays/BeatmapSetOverlay.cs | 4 +- osu.Game/Overlays/Direct/DownloadButton.cs | 101 +++++++------- .../Overlays/Direct/DownloadProgressBar.cs | 59 ++++---- .../Direct/DownloadTrackingComponent.cs | 118 +++++++++++----- 8 files changed, 295 insertions(+), 351 deletions(-) delete mode 100644 osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs deleted file mode 100644 index baeeaf81a4..0000000000 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Online.API.Requests; - -namespace osu.Game.Beatmaps.Drawables -{ - /// - /// A component to allow downloading of a beatmap set. Automatically handles state syncing between other instances. - /// - public class BeatmapSetDownloader : Component - { - private readonly BeatmapSetInfo set; - private readonly bool noVideo; - - private BeatmapManager beatmaps; - - /// - /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. - /// - public readonly Bindable DownloadState = new Bindable(); - - public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) - { - this.set = set; - this.noVideo = noVideo; - } - - [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps) - { - this.beatmaps = beatmaps; - - beatmaps.ItemAdded += setAdded; - beatmaps.ItemRemoved += setRemoved; - beatmaps.BeatmapDownloadBegan += downloadBegan; - beatmaps.BeatmapDownloadFailed += downloadFailed; - - // initial value - if (set.OnlineBeatmapSetID != null && beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any()) - DownloadState.Value = DownloadStatus.Downloaded; - else if (beatmaps.GetExistingDownload(set) != null) - DownloadState.Value = DownloadStatus.Downloading; - else - DownloadState.Value = DownloadStatus.NotDownloaded; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (beatmaps != null) - { - beatmaps.ItemAdded -= setAdded; - beatmaps.ItemRemoved -= setRemoved; - beatmaps.BeatmapDownloadBegan -= downloadBegan; - beatmaps.BeatmapDownloadFailed -= downloadFailed; - } - } - - /// - /// Begin downloading the associated beatmap set. - /// - /// True if downloading began. False if an existing download is active or completed. - public void Download() - { - if (DownloadState.Value > DownloadStatus.NotDownloaded) - return; - - if (beatmaps.Download(set, noVideo)) - { - // Only change state if download can happen - DownloadState.Value = DownloadStatus.Downloading; - } - } - - private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.Downloaded; - }); - - private void setRemoved(BeatmapSetInfo s) => Schedule(() => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.NotDownloaded; - }); - - private void downloadBegan(DownloadBeatmapSetRequest d) - { - if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.Downloading; - } - - private void downloadFailed(DownloadBeatmapSetRequest d) - { - if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.NotDownloaded; - } - - public enum DownloadStatus - { - NotDownloaded, - Downloading, - Downloaded, - } - } -} diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index c72bf8cbed..b57a077f53 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -10,7 +10,7 @@ namespace osu.Game.Online.API.Requests { public readonly BeatmapSetInfo BeatmapSet; - public Action DownloadProgressed; + public event Action DownloadProgressed; private readonly bool noVideo; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index a44e2c7fab..deaa648844 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -7,8 +7,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Overlays.Direct; @@ -18,75 +18,100 @@ using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class DownloadButton : HeaderButton, IHasTooltip + public class DownloadButton : DownloadTrackingComposite, IHasTooltip { - public string TooltipText => Enabled ? null : "You gotta be an osu!supporter to download for now 'yo"; + private readonly bool noVideo; + public string TooltipText => button.Enabled ? null : "You gotta be an osu!supporter to download for now 'yo"; private readonly IBindable localUser = new Bindable(); - public DownloadButton(BeatmapSetInfo set, bool noVideo = false) - { - Width = 120; + private ShakeContainer shakeContainer; + private HeaderButton button; - BeatmapSetDownloader downloader; + public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + : base(beatmapSet) + { + this.noVideo = noVideo; + + Width = 120; + RelativeSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load(APIAccess api, BeatmapManager beatmaps) + { FillFlowContainer textSprites; - AddRange(new Drawable[] + AddRangeInternal(new Drawable[] { - new Container + shakeContainer = new ShakeContainer { Depth = -1, RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 10 }, + Masking = true, + CornerRadius = 5, Children = new Drawable[] { - downloader = new BeatmapSetDownloader(set, noVideo), - textSprites = new FillFlowContainer + button = new HeaderButton { RelativeSizeAxes = Axes.Both }, + new Container { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - AutoSizeDuration = 500, - AutoSizeEasing = Easing.OutQuint, - Direction = FillDirection.Vertical, + // cannot nest inside here due to the structure of button (putting things in its own content). + // requires framework fix. + Padding = new MarginPadding { Horizontal = 10 }, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + textSprites = new FillFlowContainer + { + Depth = -1, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + AutoSizeDuration = 500, + AutoSizeEasing = Easing.OutQuint, + Direction = FillDirection.Vertical, + }, + new SpriteIcon + { + Depth = -1, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Icon = FontAwesome.fa_download, + Size = new Vector2(16), + Margin = new MarginPadding { Right = 5 }, + }, + } }, - new SpriteIcon + new DownloadProgressBar(BeatmapSet) { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Icon = FontAwesome.fa_download, - Size = new Vector2(16), - Margin = new MarginPadding { Right = 5 }, + Depth = -2, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, }, }, }, - new DownloadProgressBar(set) - { - Depth = -2, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - }, }); - Action = () => + button.Action = () => { - if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) + if (State.Value == DownloadState.Downloading) { - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); + shakeContainer.Shake(); return; } - downloader.Download(); + beatmaps.Download(BeatmapSet, noVideo); }; - downloader.DownloadState.ValueChanged += state => + localUser.BindTo(api.LocalUser); + localUser.BindValueChanged(userChanged, true); + button.Enabled.BindValueChanged(enabledChanged, true); + + State.BindValueChanged(state => { switch (state) { - case BeatmapSetDownloader.DownloadStatus.Downloading: + case DownloadState.Downloading: textSprites.Children = new Drawable[] { new OsuSpriteText @@ -97,10 +122,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; break; - case BeatmapSetDownloader.DownloadStatus.Downloaded: + case DownloadState.Downloaded: this.FadeOut(200); break; - case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + case DownloadState.NotDownloaded: textSprites.Children = new Drawable[] { new OsuSpriteText @@ -111,7 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, new OsuSpriteText { - Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, + Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, TextSize = 11, Font = @"Exo2.0-Bold", }, @@ -119,20 +144,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons this.FadeIn(200); break; } - }; - - downloader.DownloadState.TriggerChange(); + }, true); } - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - localUser.BindTo(api.LocalUser); - localUser.BindValueChanged(userChanged, true); - Enabled.BindValueChanged(enabledChanged, true); - } - - private void userChanged(User user) => Enabled.Value = user.IsSupporter; + private void userChanged(User user) => button.Enabled.Value = user.IsSupporter; private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index c702c7cb87..6a7fc1c0ce 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -13,12 +13,14 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.BeatmapSet.Buttons; +using osu.Game.Overlays.Direct; using osuTK; using osuTK.Graphics; +using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton; namespace osu.Game.Overlays.BeatmapSet { - public class Header : Container + public class Header : DownloadTrackingComposite { private const float transition_duration = 200; private const float tabs_height = 50; @@ -35,78 +37,16 @@ namespace osu.Game.Overlays.BeatmapSet public readonly BeatmapPicker Picker; - private BeatmapSetInfo beatmapSet; private readonly FavouriteButton favouriteButton; - public BeatmapSetInfo BeatmapSet - { - get { return beatmapSet; } - set - { - if (value == beatmapSet) return; - beatmapSet = value; - - Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet; - - updateDisplay(); - } - } - - private BeatmapSetDownloader downloader; - - private void updateDisplay() - { - downloader?.Expire(); - - - title.Text = BeatmapSet?.Metadata.Title ?? string.Empty; - artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty; - onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; - cover.BeatmapSet = BeatmapSet; - - if (BeatmapSet != null) - { - downloadButtonsContainer.FadeIn(transition_duration); - favouriteButton.FadeIn(transition_duration); - - Add(downloader = new BeatmapSetDownloader(BeatmapSet)); - downloader.DownloadState.BindValueChanged(state => - { - switch (state) - { - case BeatmapSetDownloader.DownloadStatus.Downloaded: - // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet) - { - Width = 50, - RelativeSizeAxes = Axes.Y - }; - break; - case BeatmapSetDownloader.DownloadStatus.Downloading: - // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); - break; - default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); - if (BeatmapSet.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true)); - break; - } - }, true); - } - else - { - downloadButtonsContainer.FadeOut(transition_duration); - favouriteButton.FadeOut(transition_duration); - } - } - public Header() { ExternalLinkButton externalLink; + RelativeSizeAxes = Axes.X; Height = 400; Masking = true; + EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0.25f), @@ -114,7 +54,8 @@ namespace osu.Game.Overlays.BeatmapSet Radius = 3, Offset = new Vector2(0f, 1f), }; - Children = new Drawable[] + + InternalChildren = new Drawable[] { new Container { @@ -241,14 +182,64 @@ namespace osu.Game.Overlays.BeatmapSet }; Picker.Beatmap.ValueChanged += b => Details.Beatmap = b; - Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; + Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; } [BackgroundDependencyLoader] private void load(OsuColour colours) { tabsBg.Colour = colours.Gray3; - updateDisplay(); + + BeatmapSet.BindValueChanged(beatmapSet => + { + Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = beatmapSet; + + title.Text = beatmapSet?.Metadata.Title ?? string.Empty; + artist.Text = beatmapSet?.Metadata.Artist ?? string.Empty; + onlineStatusPill.Status = beatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; + cover.BeatmapSet = beatmapSet; + + if (beatmapSet != null) + { + downloadButtonsContainer.FadeIn(transition_duration); + favouriteButton.FadeIn(transition_duration); + } + else + { + downloadButtonsContainer.FadeOut(transition_duration); + favouriteButton.FadeOut(transition_duration); + } + + updateDownloadButtons(); + }); + + State.BindValueChanged(_ => updateDownloadButtons(), true); + } + + private void updateDownloadButtons() + { + if (BeatmapSet.Value == null) return; + switch (State.Value) + { + case DownloadState.LocallyAvailable: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet) + { + Width = 50, + RelativeSizeAxes = Axes.Y + }; + break; + case DownloadState.Downloading: + case DownloadState.Downloaded: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + break; + default: + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + if (BeatmapSet.Value.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true)); + break; + } } } } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 6294851415..84d7861aa0 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays if (value == beatmapSet) return; - header.BeatmapSet = info.BeatmapSet = beatmapSet = value; + header.BeatmapSet.Value = info.BeatmapSet = beatmapSet = value; } } @@ -140,7 +140,7 @@ namespace osu.Game.Overlays req.Success += res => { BeatmapSet = res.ToBeatmapSet(rulesets); - header.Picker.Beatmap.Value = header.BeatmapSet.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); + header.Picker.Beatmap.Value = header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); }; api.Queue(req); Show(); diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index e326f5e592..32cc8b351a 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -5,103 +5,114 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Overlays.Direct { - public class DownloadButton : OsuAnimatedButton + public class DownloadButton : DownloadTrackingComposite { - private readonly BeatmapSetInfo beatmapSet; + private readonly bool noVideo; private readonly SpriteIcon icon; private readonly SpriteIcon checkmark; - private readonly BeatmapSetDownloader downloader; private readonly Box background; private OsuColour colours; - public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) - { - this.beatmapSet = beatmapSet; + private readonly ShakeContainer shakeContainer; - AddRange(new Drawable[] + private readonly OsuAnimatedButton button; + + public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + : base(beatmapSet) + { + this.noVideo = noVideo; + + InternalChild = shakeContainer = new ShakeContainer { - downloader = new BeatmapSetDownloader(beatmapSet, noVideo), - background = new Box + RelativeSizeAxes = Axes.Both, + Child = button = new OsuAnimatedButton { RelativeSizeAxes = Axes.Both, - Depth = float.MaxValue - }, - icon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(13), - Icon = FontAwesome.fa_download, - }, - checkmark = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - X = 8, - Size = Vector2.Zero, - Icon = FontAwesome.fa_check, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue + }, + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(13), + Icon = FontAwesome.fa_download, + }, + checkmark = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + X = 8, + Size = Vector2.Zero, + Icon = FontAwesome.fa_check, + } + } } - }); + }; } protected override void LoadComplete() { base.LoadComplete(); - downloader.DownloadState.BindValueChanged(updateState, true); + + State.BindValueChanged(updateState, true); FinishTransforms(true); } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame game) + private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps) { this.colours = colours; - Action = () => + button.Action = () => { - switch (downloader.DownloadState.Value) + switch (State.Value) { - case BeatmapSetDownloader.DownloadStatus.Downloading: - // todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged. - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); + case DownloadState.Downloading: + case DownloadState.Downloaded: + shakeContainer.Shake(); break; - case BeatmapSetDownloader.DownloadStatus.Downloaded: - game.PresentBeatmap(beatmapSet); + case DownloadState.LocallyAvailable: + game.PresentBeatmap(BeatmapSet); break; default: - downloader.Download(); + beatmaps.Download(BeatmapSet, noVideo); break; } }; } - private void updateState(BeatmapSetDownloader.DownloadStatus state) + private void updateState(DownloadState state) { switch (state) { - case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + case DownloadState.NotDownloaded: background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); break; - case BeatmapSetDownloader.DownloadStatus.Downloading: + case DownloadState.Downloading: background.FadeColour(colours.Blue, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); break; - - case BeatmapSetDownloader.DownloadStatus.Downloaded: + case DownloadState.Downloaded: + background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); + break; + case DownloadState.LocallyAvailable: background.FadeColour(colours.Green, 500, Easing.InOutExpo); icon.MoveToX(-8, 500, Easing.InOutExpo); checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index 60632980a7..b416377d0f 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -11,14 +11,12 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Direct { - public class DownloadProgressBar : DownloadTrackingComponent + public class DownloadProgressBar : DownloadTrackingComposite { private readonly ProgressBar progressBar; - private OsuColour colours; - - public DownloadProgressBar(BeatmapSetInfo setInfo) - : base(setInfo) + public DownloadProgressBar(BeatmapSetInfo beatmapSet) + : base(beatmapSet) { AddInternal(progressBar = new ProgressBar { @@ -33,38 +31,31 @@ namespace osu.Game.Overlays.Direct [BackgroundDependencyLoader(true)] private void load(OsuColour colours) { - this.colours = colours; - progressBar.FillColour = colours.Blue; progressBar.BackgroundColour = Color4.Black.Opacity(0.7f); - } + progressBar.Current = Progress; - protected override void DownloadFailed() - { - progressBar.Current.Value = 0; - progressBar.FadeOut(500); - } - - protected override void DownloadComleted() - { - progressBar.Current.Value = 1; - progressBar.FillColour = colours.Yellow; - } - - protected override void DownloadStarted() - { - progressBar.FadeIn(400, Easing.OutQuint); - progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); - } - - protected override void BeatmapImported() - { - progressBar.FadeOut(500); - } - - protected override void ProgressChanged(float progress) - { - progressBar.Current.Value = progress; + State.BindValueChanged(state => + { + switch (state) + { + case DownloadState.NotDownloaded: + progressBar.Current.Value = 0; + progressBar.FadeOut(500); + break; + case DownloadState.Downloading: + progressBar.FadeIn(400, Easing.OutQuint); + progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); + break; + case DownloadState.Downloaded: + progressBar.Current.Value = 1; + progressBar.FillColour = colours.Yellow; + break; + case DownloadState.LocallyAvailable: + progressBar.FadeOut(500); + break; + } + }, true); } } } diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs b/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs index 8b42832554..0bfb28978f 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs @@ -1,21 +1,56 @@ -// Copyright (c) 2007-2019 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests; namespace osu.Game.Overlays.Direct { - public abstract class DownloadTrackingComponent : CompositeDrawable + public abstract class DownloadTrackingComposite : CompositeDrawable { - private readonly BeatmapSetInfo setInfo; + public readonly Bindable BeatmapSet = new Bindable(); + private BeatmapManager beatmaps; - protected DownloadTrackingComponent(BeatmapSetInfo beatmapSetInfo) + /// + /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. + /// + protected readonly Bindable State = new Bindable(); + + protected readonly Bindable Progress = new Bindable(); + + protected DownloadTrackingComposite(BeatmapSetInfo beatmapSet = null) { - setInfo = beatmapSetInfo; + BeatmapSet.Value = beatmapSet; + } + + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps) + { + this.beatmaps = beatmaps; + + BeatmapSet.BindValueChanged(set => + { + if (set == null) + attachDownload(null); + else if (beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID).Any()) + State.Value = DownloadState.LocallyAvailable; + else + attachDownload(beatmaps.GetExistingDownload(set)); + }, true); + + beatmaps.BeatmapDownloadBegan += download => + { + if (download.BeatmapSet.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) + attachDownload(download); + }; + + beatmaps.ItemAdded += setAdded; } #region Disposal @@ -29,49 +64,62 @@ namespace osu.Game.Overlays.Direct #endregion - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps) - { - this.beatmaps = beatmaps; - - var downloadRequest = beatmaps.GetExistingDownload(setInfo); - - if (downloadRequest != null) - attachDownload(downloadRequest); - - beatmaps.BeatmapDownloadBegan += attachDownload; - beatmaps.ItemAdded += setAdded; - } + private DownloadBeatmapSetRequest attachedRequest; private void attachDownload(DownloadBeatmapSetRequest request) { - if (request.BeatmapSet.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) - return; + if (attachedRequest != null) + { + attachedRequest.Failure -= onRequestFailure; + attachedRequest.DownloadProgressed -= onRequestProgress; + attachedRequest.Success -= onRequestSuccess; + } - DownloadStarted(); + attachedRequest = request; - request.Failure += e => { DownloadFailed(); }; - - request.DownloadProgressed += progress => Schedule(() => ProgressChanged(progress)); - request.Success += data => { DownloadComleted(); }; + if (attachedRequest != null) + { + State.Value = DownloadState.Downloading; + attachedRequest.Failure += onRequestFailure; + attachedRequest.DownloadProgressed += onRequestProgress; + attachedRequest.Success += onRequestSuccess; + } + else + { + State.Value = DownloadState.NotDownloaded; + } } - protected abstract void ProgressChanged(float progress); + private void onRequestSuccess(byte[] data) + { + Schedule(() => State.Value = DownloadState.Downloaded); + attachDownload(null); + } - protected abstract void DownloadFailed(); + private void onRequestProgress(float progress) + { + Schedule(() => Progress.Value = progress); + } - protected abstract void DownloadComleted(); - - protected abstract void BeatmapImported(); - - protected abstract void DownloadStarted(); + private void onRequestFailure(Exception e) + { + Schedule(() => State.Value = DownloadState.Downloading); + } private void setAdded(BeatmapSetInfo s, bool existing, bool silent) { - if (s.OnlineBeatmapSetID != setInfo.OnlineBeatmapSetID) + if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID) return; - Schedule(BeatmapImported); + Schedule(() => State.Value = DownloadState.LocallyAvailable); } } -} \ No newline at end of file + + public enum DownloadState + { + NotDownloaded, + Downloading, + Downloaded, + LocallyAvailable + } +} From f489718e250a6c27881eb9a3f68bf2bad9b34262 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Jan 2019 14:33:40 +0900 Subject: [PATCH 04/18] Fix non-matching filename --- osu.Game/Overlays/Direct/DownloadState.cs | 13 +++++++++++++ ...ingComponent.cs => DownloadTrackingComposite.cs} | 8 -------- 2 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Overlays/Direct/DownloadState.cs rename osu.Game/Overlays/Direct/{DownloadTrackingComponent.cs => DownloadTrackingComposite.cs} (96%) diff --git a/osu.Game/Overlays/Direct/DownloadState.cs b/osu.Game/Overlays/Direct/DownloadState.cs new file mode 100644 index 0000000000..6fd48b86c3 --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadState.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Overlays.Direct +{ + public enum DownloadState + { + NotDownloaded, + Downloading, + Downloaded, + LocallyAvailable + } +} diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs similarity index 96% rename from osu.Game/Overlays/Direct/DownloadTrackingComponent.cs rename to osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 0bfb28978f..0d5055f5b7 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComponent.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -114,12 +114,4 @@ namespace osu.Game.Overlays.Direct Schedule(() => State.Value = DownloadState.LocallyAvailable); } } - - public enum DownloadState - { - NotDownloaded, - Downloading, - Downloaded, - LocallyAvailable - } } From cebeb0a2190946f9100b857f62facb7b46e58276 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 11:40:57 +0900 Subject: [PATCH 05/18] Fix replay playback speed not being displayed initially --- .../Play/PlayerSettings/PlaybackSettings.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 13e403e899..cba6a88c4e 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -19,10 +19,10 @@ namespace osu.Game.Screens.Play.PlayerSettings private readonly PlayerSliderBar sliderbar; + private readonly OsuSpriteText multiplierText; + public PlaybackSettings() { - OsuSpriteText multiplierText; - Children = new Drawable[] { new Container @@ -57,9 +57,6 @@ namespace osu.Game.Screens.Play.PlayerSettings }, } }; - - sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{sliderbar.Bar.TooltipText}x"; - sliderbar.Bindable.TriggerChange(); } protected override void LoadComplete() @@ -70,7 +67,12 @@ namespace osu.Game.Screens.Play.PlayerSettings return; var clockRate = AdjustableClock.Rate; - sliderbar.Bindable.ValueChanged += rateMultiplier => AdjustableClock.Rate = clockRate * rateMultiplier; + + sliderbar.Bindable.BindValueChanged(multiplier => + { + multiplierText.Text = $"{multiplier:0.0}x"; + AdjustableClock.Rate = clockRate * multiplier; + }, true); } } } From c58fe4f4ffed4f44d31ca11081b8204087bc921e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Jan 2019 13:18:01 +0900 Subject: [PATCH 06/18] Fix nullref --- osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index cba6a88c4e..8ad0e14137 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -68,11 +68,10 @@ namespace osu.Game.Screens.Play.PlayerSettings var clockRate = AdjustableClock.Rate; - sliderbar.Bindable.BindValueChanged(multiplier => - { - multiplierText.Text = $"{multiplier:0.0}x"; - AdjustableClock.Rate = clockRate * multiplier; - }, true); + // can't trigger this line instantly as the underlying clock may not be ready to accept adjustments yet. + sliderbar.Bindable.ValueChanged += multiplier => AdjustableClock.Rate = clockRate * multiplier; + + sliderbar.Bindable.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier:0.0}x", true); } } } From a208874e740510d0532676924c40bd7d06c09d8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Jan 2019 11:59:10 +0900 Subject: [PATCH 07/18] Fix incorrect handling of download failures --- osu.Game/Overlays/Direct/DownloadTrackingComposite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 0d5055f5b7..dcd1c8cb03 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -103,7 +103,7 @@ namespace osu.Game.Overlays.Direct private void onRequestFailure(Exception e) { - Schedule(() => State.Value = DownloadState.Downloading); + Schedule(() => State.Value = DownloadState.NotDownloaded); } private void setAdded(BeatmapSetInfo s, bool existing, bool silent) From 23d0399e516b5bee581ccf4d80e0bbb128cfe382 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Jan 2019 17:01:53 +0900 Subject: [PATCH 08/18] Allow deselection of textboxes on registration screen on mobile devices --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index b0d08d3c6c..4b835b446e 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -10,6 +10,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; +using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -38,11 +39,13 @@ namespace osu.Game.Overlays.AccountCreation private OsuTextBox[] textboxes; private ProcessingOverlay processingOverlay; + private GameHost host; [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api) + private void load(OsuColour colours, APIAccess api, GameHost host) { this.api = api; + this.host = host; Children = new Drawable[] { @@ -139,7 +142,7 @@ namespace osu.Game.Overlays.AccountCreation { base.Update(); - if (!textboxes.Any(t => t.HasFocus)) + if (host?.OnScreenKeyboardOverlapsGameWindow != true && !textboxes.Any(t => t.HasFocus)) focusNextTextbox(); } From 7f2fdac50e67009e4962e37c48890427bf1342cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 18:47:30 +0900 Subject: [PATCH 09/18] Update signatures --- osu.Game/Overlays/Direct/DownloadTrackingComposite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index dcd1c8cb03..4b68c3824a 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Direct } } - private void onRequestSuccess(byte[] data) + private void onRequestSuccess(string data) { Schedule(() => State.Value = DownloadState.Downloaded); attachDownload(null); From c54a515b3e95588f2ab6a7c545304104109d0fdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 18:49:54 +0900 Subject: [PATCH 10/18] Change where BindValueChange is immediately run --- osu.Game/Overlays/BeatmapSet/Header.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index c57b70a48c..8721a1ce5a 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -190,6 +190,8 @@ namespace osu.Game.Overlays.BeatmapSet { tabsBg.Colour = colours.Gray3; + State.BindValueChanged(_ => updateDownloadButtons()); + BeatmapSet.BindValueChanged(beatmapSet => { Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = beatmapSet; @@ -211,9 +213,7 @@ namespace osu.Game.Overlays.BeatmapSet } updateDownloadButtons(); - }); - - State.BindValueChanged(_ => updateDownloadButtons(), true); + }, true); } private void updateDownloadButtons() From b69a19f81044d7b3f13188b1e15a4b670e1a914e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:08:45 +0900 Subject: [PATCH 11/18] Attach progress immediately --- osu.Game/Online/API/APIDownloadRequest.cs | 4 ++-- .../API/Requests/DownloadBeatmapSetRequest.cs | 4 +++- .../Direct/DownloadTrackingComposite.cs | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index 97b869bccd..efc832a71e 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -17,7 +17,7 @@ namespace osu.Game.Online.API return request; } - private void request_Progress(long current, long total) => API.Schedule(() => Progress?.Invoke(current, total)); + private void request_Progress(long current, long total) => API.Schedule(() => Progressed?.Invoke(current, total)); protected APIDownloadRequest() { @@ -29,7 +29,7 @@ namespace osu.Game.Online.API Success?.Invoke(filename); } - public event APIProgressHandler Progress; + public event APIProgressHandler Progressed; public new event APISuccessHandler Success; } diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index cd55e9b300..26e8acc2fc 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -10,6 +10,8 @@ namespace osu.Game.Online.API.Requests { public readonly BeatmapSetInfo BeatmapSet; + public float Progress; + public event Action DownloadProgressed; private readonly bool noVideo; @@ -19,7 +21,7 @@ namespace osu.Game.Online.API.Requests this.noVideo = noVideo; BeatmapSet = set; - Progress += (current, total) => DownloadProgressed?.Invoke((float) current / total); + Progressed += (current, total) => DownloadProgressed?.Invoke(Progress = (float)current / total); } protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 4b68c3824a..733bcf877e 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -79,10 +79,20 @@ namespace osu.Game.Overlays.Direct if (attachedRequest != null) { - State.Value = DownloadState.Downloading; - attachedRequest.Failure += onRequestFailure; - attachedRequest.DownloadProgressed += onRequestProgress; - attachedRequest.Success += onRequestSuccess; + if (attachedRequest.Progress == 1) + { + State.Value = DownloadState.Downloaded; + Progress.Value = 1; + } + else + { + State.Value = DownloadState.Downloading; + Progress.Value = attachedRequest.Progress; + + attachedRequest.Failure += onRequestFailure; + attachedRequest.DownloadProgressed += onRequestProgress; + attachedRequest.Success += onRequestSuccess; + } } else { From 041e3bf823cf17e6edf6475645fdb1a5f94abf81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:08:54 +0900 Subject: [PATCH 12/18] Handle unbinding better --- osu.Game/Overlays/Direct/DownloadTrackingComposite.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 733bcf877e..fddbefdf4d 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -58,8 +58,13 @@ namespace osu.Game.Overlays.Direct protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + beatmaps.BeatmapDownloadBegan -= attachDownload; beatmaps.ItemAdded -= setAdded; + + State.UnbindAll(); + + attachDownload(null); } #endregion @@ -103,7 +108,6 @@ namespace osu.Game.Overlays.Direct private void onRequestSuccess(string data) { Schedule(() => State.Value = DownloadState.Downloaded); - attachDownload(null); } private void onRequestProgress(float progress) @@ -113,7 +117,7 @@ namespace osu.Game.Overlays.Direct private void onRequestFailure(Exception e) { - Schedule(() => State.Value = DownloadState.NotDownloaded); + Schedule(() => attachDownload(null)); } private void setAdded(BeatmapSetInfo s, bool existing, bool silent) From b89694a96935efc76a2c13f962b9017a04bbf3ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:09:04 +0900 Subject: [PATCH 13/18] Fix "importing" state display --- .../Overlays/BeatmapSet/Buttons/DownloadButton.cs | 11 +++++++++++ osu.Game/Overlays/Direct/DownloadProgressBar.cs | 1 + 2 files changed, 12 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 7c0ffaddcb..de0ced3f08 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -124,6 +124,17 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }; break; case DownloadState.Downloaded: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Importing...", + TextSize = 13, + Font = @"Exo2.0-Bold", + }, + }; + break; + case DownloadState.LocallyAvailable: this.FadeOut(200); break; case DownloadState.NotDownloaded: diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index b416377d0f..cc5a98c575 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -48,6 +48,7 @@ namespace osu.Game.Overlays.Direct progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); break; case DownloadState.Downloaded: + progressBar.FadeIn(400, Easing.OutQuint); progressBar.Current.Value = 1; progressBar.FillColour = colours.Yellow; break; From 0b8bd520abee4dd9c67594483d7cc8c3718050d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:15:04 +0900 Subject: [PATCH 14/18] Shake in all cases --- osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index de0ced3f08..4d46d41c0f 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons button.Action = () => { - if (State.Value == DownloadState.Downloading) + if (State.Value != DownloadState.NotDownloaded) { shakeContainer.Shake(); return; From 7c6512118e320ca1df32125fd95066e1a73e0c71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:15:17 +0900 Subject: [PATCH 15/18] Fix importing progress bar not displaying --- osu.Game/Overlays/Direct/DownloadProgressBar.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index cc5a98c575..c73ce38c54 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -49,6 +49,8 @@ namespace osu.Game.Overlays.Direct break; case DownloadState.Downloaded: progressBar.FadeIn(400, Easing.OutQuint); + progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); + progressBar.Current.Value = 1; progressBar.FillColour = colours.Yellow; break; From c7cf3ef1cda7df0bbffe22160242107016e7e9d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:17:42 +0900 Subject: [PATCH 16/18] Update licence headers --- osu.Game/Overlays/Direct/DownloadProgressBar.cs | 4 ++-- osu.Game/Overlays/Direct/DownloadState.cs | 4 ++-- osu.Game/Overlays/Direct/DownloadTrackingComposite.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index c73ce38c54..4ac1aba7f5 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Direct/DownloadState.cs b/osu.Game/Overlays/Direct/DownloadState.cs index 6fd48b86c3..a301c6a3bd 100644 --- a/osu.Game/Overlays/Direct/DownloadState.cs +++ b/osu.Game/Overlays/Direct/DownloadState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Overlays.Direct { diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index fddbefdf4d..f255403e81 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Microsoft.EntityFrameworkCore.Internal; From d1c8ee65a5b3c24f622397fd67b1913a821577a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Jan 2019 19:22:29 +0900 Subject: [PATCH 17/18] Fix osu! logo potentially appearing during game load in a weird place --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3cc040ecb1..b1f18341d2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -169,7 +169,7 @@ namespace osu.Game dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); - dependencies.Cache(osuLogo = new OsuLogo()); + dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 }); // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); From 257321b500d51307404774e552184a3a41392b85 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sat, 2 Feb 2019 12:26:23 -0800 Subject: [PATCH 18/18] Move regular issue template to .github --- ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md (100%) diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE.md