diff --git a/osu.Android.props b/osu.Android.props index c28085557e..116c7dbfcd 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index 35a4f8cf2d..edee26c081 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs @@ -11,6 +11,7 @@ using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; +using osu.Game.Overlays; using osu.Game.Overlays.Dashboard; using osu.Game.Tests.Visual.Spectator; using osu.Game.Users; @@ -42,7 +43,8 @@ namespace osu.Game.Tests.Visual.Online CachedDependencies = new (Type, object)[] { (typeof(SpectatorClient), spectatorClient), - (typeof(UserLookupCache), lookupCache) + (typeof(UserLookupCache), lookupCache), + (typeof(OverlayColourProvider), new OverlayColourProvider(OverlayColourScheme.Purple)), }, Child = currentlyPlaying = new CurrentlyPlayingDisplay { diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 80dfa104f3..ae2b85da51 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,11 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Toolkit.HighPerformance; +using osu.Framework.Extensions; using osu.Framework.IO.Stores; using SharpCompress.Archives.Zip; +using SixLabors.ImageSharp.Memory; namespace osu.Game.IO.Archives { @@ -27,15 +31,12 @@ namespace osu.Game.IO.Archives if (entry == null) throw new FileNotFoundException(); - // allow seeking - MemoryStream copy = new MemoryStream(); + var owner = MemoryAllocator.Default.Allocate((int)entry.Size); using (Stream s = entry.OpenEntryStream()) - s.CopyTo(copy); + s.ReadToFill(owner.Memory.Span); - copy.Position = 0; - - return copy; + return new MemoryOwnerMemoryStream(owner); } public override void Dispose() @@ -45,5 +46,48 @@ namespace osu.Game.IO.Archives } public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); + + private class MemoryOwnerMemoryStream : Stream + { + private readonly IMemoryOwner owner; + private readonly Stream stream; + + public MemoryOwnerMemoryStream(IMemoryOwner owner) + { + this.owner = owner; + + stream = owner.Memory.AsStream(); + } + + protected override void Dispose(bool disposing) + { + owner?.Dispose(); + base.Dispose(disposing); + } + + public override void Flush() => stream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) => stream.Read(buffer, offset, count); + + public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin); + + public override void SetLength(long value) => stream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) => stream.Write(buffer, offset, count); + + public override bool CanRead => stream.CanRead; + + public override bool CanSeek => stream.CanSeek; + + public override bool CanWrite => stream.CanWrite; + + public override long Length => stream.Length; + + public override long Position + { + get => stream.Position; + set => stream.Position = value; + } + } } } diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index a9312e9a3a..23f67a06cb 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -9,11 +10,16 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Screens; using osu.Game.Database; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; +using osu.Game.Resources.Localisation.Web; using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.Play; @@ -24,26 +30,62 @@ namespace osu.Game.Overlays.Dashboard { internal class CurrentlyPlayingDisplay : CompositeDrawable { + private const float search_textbox_height = 40; + private const float padding = 10; + private readonly IBindableList playingUsers = new BindableList(); - private FillFlowContainer userFlow; + private SearchContainer userFlow; + private BasicSearchTextBox searchTextBox; [Resolved] private SpectatorClient spectatorClient { get; set; } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colourProvider) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChild = userFlow = new FillFlowContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(10), - Spacing = new Vector2(10), + new Box + { + RelativeSizeAxes = Axes.X, + Height = padding * 2 + search_textbox_height, + Colour = colourProvider.Background4, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding(padding), + Child = searchTextBox = new BasicSearchTextBox + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Height = search_textbox_height, + ReleaseFocusOnCommit = false, + HoldFocus = true, + PlaceholderText = HomeStrings.SearchPlaceholder, + }, + }, + userFlow = new SearchContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + Padding = new MarginPadding + { + Top = padding * 3 + search_textbox_height, + Bottom = padding, + Right = padding, + Left = padding, + }, + }, }; + + searchTextBox.Current.ValueChanged += text => userFlow.SearchTerm = text.NewValue; } [Resolved] @@ -57,6 +99,13 @@ namespace osu.Game.Overlays.Dashboard playingUsers.BindCollectionChanged(onPlayingUsersChanged, true); } + protected override void OnFocus(FocusEvent e) + { + base.OnFocus(e); + + searchTextBox.TakeFocus(); + } + private void onPlayingUsersChanged(object sender, NotifyCollectionChangedEventArgs e) => Schedule(() => { switch (e.Action) @@ -102,17 +151,34 @@ namespace osu.Game.Overlays.Dashboard panel.Origin = Anchor.TopCentre; }); - private class PlayingUserPanel : CompositeDrawable + public class PlayingUserPanel : CompositeDrawable, IFilterable { public readonly APIUser User; + public IEnumerable FilterTerms { get; } + [Resolved(canBeNull: true)] private IPerformFromScreenRunner performer { get; set; } + public bool FilteringActive { set; get; } + + public bool MatchingFilter + { + set + { + if (value) + Show(); + else + Hide(); + } + } + public PlayingUserPanel(APIUser user) { User = user; + FilterTerms = new LocalisableString[] { User.Username }; + AutoSizeAxes = Axes.Both; } diff --git a/osu.Game/Overlays/DashboardOverlay.cs b/osu.Game/Overlays/DashboardOverlay.cs index 83ad8faf1c..79d972bdcc 100644 --- a/osu.Game/Overlays/DashboardOverlay.cs +++ b/osu.Game/Overlays/DashboardOverlay.cs @@ -16,6 +16,8 @@ namespace osu.Game.Overlays protected override DashboardOverlayHeader CreateHeader() => new DashboardOverlayHeader(); + public override bool AcceptsFocus => false; + protected override void CreateDisplayToLoad(DashboardOverlayTabs tab) { switch (tab) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 79cfd7c917..eb47d0468f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,13 +29,14 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index b1ba64beba..ccecad6f82 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -61,7 +61,7 @@ - + @@ -84,7 +84,7 @@ - +