From 0da0ef5a1bf6ae26fc5586e2e1627b5ddd3b1b60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 17:06:41 +0900 Subject: [PATCH 01/18] Fix padding, fonts and alignment of chat display. --- osu.Game/Online/Chat/Drawables/ChatLine.cs | 13 ++++++++----- .../{ChannelDisplay.cs => DrawableChannel.cs} | 4 ++-- osu.Game/Overlays/ChatOverlay.cs | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) rename osu.Game/Online/Chat/Drawables/{ChannelDisplay.cs => DrawableChannel.cs} (93%) diff --git a/osu.Game/Online/Chat/Drawables/ChatLine.cs b/osu.Game/Online/Chat/Drawables/ChatLine.cs index 21c6659e7868..3780f6861556 100644 --- a/osu.Game/Online/Chat/Drawables/ChatLine.cs +++ b/osu.Game/Online/Chat/Drawables/ChatLine.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -15,7 +14,7 @@ public class ChatLine : Container { public readonly Message Message; - const float padding = 200; + const float padding = 250; const float text_size = 20; public ChatLine(Message message) @@ -25,6 +24,8 @@ public ChatLine(Message message) RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Left = 15, Right = 15 }; + Children = new Drawable[] { new Container @@ -34,13 +35,15 @@ public ChatLine(Message message) { new OsuSpriteText { - Text = Message.Timestamp.LocalDateTime.ToLongTimeString(), + Text = $@"{Message.Timestamp.LocalDateTime:hh:mm:ss}", + FixedWidth = true, TextSize = text_size, Colour = Color4.Gray }, new OsuSpriteText { - Text = Message.User.Name, + Font = @"Exo2.0-BoldItalic", + Text = $@"{Message.User.Name}:", TextSize = text_size, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, @@ -51,7 +54,7 @@ public ChatLine(Message message) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = padding + 10 }, + Padding = new MarginPadding { Left = padding + 15 }, Children = new Drawable[] { new OsuSpriteText diff --git a/osu.Game/Online/Chat/Drawables/ChannelDisplay.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs similarity index 93% rename from osu.Game/Online/Chat/Drawables/ChannelDisplay.cs rename to osu.Game/Online/Chat/Drawables/DrawableChannel.cs index cc6070683100..d2968a732b72 100644 --- a/osu.Game/Online/Chat/Drawables/ChannelDisplay.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -13,12 +13,12 @@ namespace osu.Game.Online.Chat.Drawables { - public class ChannelDisplay : Container + public class DrawableChannel : Container { private readonly Channel channel; private FlowContainer flow; - public ChannelDisplay(Channel channel) + public DrawableChannel(Channel channel) { this.channel = channel; newMessages(channel.Messages); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index f99936763f17..b9ac55bff076 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays { public class ChatOverlay : OverlayContainer, IOnlineComponent { - private ChannelDisplay channelDisplay; + private DrawableChannel channelDisplay; private ScheduledDelegate messageRequest; @@ -69,7 +69,7 @@ private void load(APIAccess api) private void addChannel(Channel channel) { - Add(channelDisplay = new ChannelDisplay(channel)); + Add(channelDisplay = new DrawableChannel(channel)); careChannels.Add(channel); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 632e35037b52..55eee483bdd7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -189,7 +189,7 @@ - + From 2a099bb56cbb4d60d94cf9de05f96521ac6f469f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 17:06:51 +0900 Subject: [PATCH 02/18] Stop TestCaseChatDisplay basically reimplementing ChatOverlay. --- .../Tests/TestCaseChatDisplay.cs | 110 +----------------- 1 file changed, 4 insertions(+), 106 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs index d977e9cede81..4e27788d6765 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs @@ -17,6 +17,7 @@ using OpenTK; using osu.Framework.Allocation; using osu.Game.Online.Chat.Drawables; +using osu.Game.Overlays; namespace osu.Desktop.VisualTests.Tests { @@ -25,119 +26,16 @@ class TestCaseChatDisplay : TestCase private ScheduledDelegate messageRequest; public override string Name => @"Chat"; - public override string Description => @"Testing API polling"; - - FlowContainer flow; - - private Scheduler scheduler = new Scheduler(); - - private APIAccess api; - - private ChannelDisplay channelDisplay; - - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - this.api = api; - } + public override string Description => @"Testing chat api and overlay"; public override void Reset() { base.Reset(); - if (api.State != APIState.Online) - api.OnStateChange += delegate { initializeChannels(); }; - else - initializeChannels(); - } - - protected override void Update() - { - scheduler.Update(); - base.Update(); - } - - private long? lastMessageId; - - List careChannels; - - private void initializeChannels() - { - careChannels = new List(); - - if (api.State != APIState.Online) - return; - - Add(flow = new FlowContainer + Add(new ChatOverlay() { - RelativeSizeAxes = Axes.Both, - Direction = FlowDirections.Vertical + State = Visibility.Visible }); - - SpriteText loading; - Add(loading = new SpriteText - { - Text = @"Loading available channels...", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - TextSize = 40, - }); - - messageRequest?.Cancel(); - - ListChannelsRequest req = new ListChannelsRequest(); - req.Success += delegate (List channels) - { - Scheduler.Add(delegate - { - loading.FadeOut(100); - }); - - addChannel(channels.Find(c => c.Name == @"#osu")); - addChannel(channels.Find(c => c.Name == @"#lobby")); - addChannel(channels.Find(c => c.Name == @"#english")); - - messageRequest = scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true); - }; - api.Queue(req); - } - - private void addChannel(Channel channel) - { - flow.Add(channelDisplay = new ChannelDisplay(channel) - { - Size = new Vector2(1, 0.3f) - }); - - careChannels.Add(channel); - } - - GetMessagesRequest fetchReq; - - public void FetchNewMessages(APIAccess api) - { - if (fetchReq != null) return; - - fetchReq = new GetMessagesRequest(careChannels, lastMessageId); - fetchReq.Success += delegate (List messages) - { - foreach (Message m in messages) - { - careChannels.Find(c => c.Id == m.ChannelId).AddNewMessages(m); - } - - lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId; - - Debug.Write("success!"); - fetchReq = null; - }; - fetchReq.Failure += delegate - { - Debug.Write("failure!"); - fetchReq = null; - }; - - api.Queue(fetchReq); } } } From 520e04039688374e5b1f2863ca5a25dd5bfba4ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 17:59:22 +0900 Subject: [PATCH 03/18] Add FocusedTextBox abstraction. --- .../Graphics/UserInterface/FocusedTextBox.cs | 49 +++++++++++++++++++ osu.Game/Graphics/UserInterface/OsuTextBox.cs | 1 - osu.Game/Screens/Select/FilterControl.cs | 17 ++++--- osu.Game/Screens/Select/SearchTextBox.cs | 39 +-------------- osu.Game/osu.Game.csproj | 1 + 5 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/FocusedTextBox.cs diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs new file mode 100644 index 000000000000..f657ffe33045 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -0,0 +1,49 @@ +using OpenTK.Graphics; +using OpenTK.Input; +using osu.Framework.Input; +using System; +using System.Linq; + +namespace osu.Game.Graphics.UserInterface +{ + public class FocusedTextBox : OsuTextBox + { + protected override Color4 BackgroundUnfocused => new Color4(10, 10, 10, 255); + protected override Color4 BackgroundFocused => new Color4(10, 10, 10, 255); + + public Action Exit; + + private bool focus; + public bool HoldFocus + { + get { return focus; } + set + { + focus = value; + if (!focus) + TriggerFocusLost(); + } + } + + protected override bool OnFocus(InputState state) + { + var result = base.OnFocus(state); + BorderThickness = 0; + return result; + } + + protected override void OnFocusLost(InputState state) + { + if (state.Keyboard.Keys.Any(key => key == Key.Escape)) + { + if (Text.Length > 0) + Text = string.Empty; + else + Exit?.Invoke(); + } + base.OnFocusLost(state); + } + + public override bool RequestingFocus => HoldFocus; + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 0e551380ed37..d7bc245027ea 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays; using OpenTK.Graphics; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 975a3f9ca337..23a61459ea45 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -47,18 +47,19 @@ public FilterControl() Direction = FlowDirections.Vertical, Children = new Drawable[] { - searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X }, + searchTextBox = new SearchTextBox { + RelativeSizeAxes = Axes.X, + OnChange = (TextBox sender, bool newText) => + { + if (newText) + FilterChanged?.Invoke(); + }, + Exit = () => Exit?.Invoke(), + }, new GroupSortTabs() } } }; - - searchTextBox.OnChange += (TextBox sender, bool newText) => - { - if (newText) - FilterChanged?.Invoke(); - }; - searchTextBox.Exit = () => Exit?.Invoke(); } public void Deactivate() diff --git a/osu.Game/Screens/Select/SearchTextBox.cs b/osu.Game/Screens/Select/SearchTextBox.cs index 4cd5353712e1..aeb9db75db27 100644 --- a/osu.Game/Screens/Select/SearchTextBox.cs +++ b/osu.Game/Screens/Select/SearchTextBox.cs @@ -16,26 +16,8 @@ namespace osu.Game.Screens.Select /// /// A textbox which holds focus eagerly. /// - public class SearchTextBox : OsuTextBox + public class SearchTextBox : FocusedTextBox { - protected override Color4 BackgroundUnfocused => new Color4(10, 10, 10, 255); - protected override Color4 BackgroundFocused => new Color4(10, 10, 10, 255); - public Action Exit; - - private bool focus; - public bool HoldFocus - { - get { return focus; } - set - { - focus = value; - if (!focus) - TriggerFocusLost(); - } - } - - public override bool RequestingFocus => HoldFocus; - public SearchTextBox() { Height = 35; @@ -53,25 +35,6 @@ public SearchTextBox() PlaceholderText = "type to search"; } - protected override bool OnFocus(InputState state) - { - var result = base.OnFocus(state); - BorderThickness = 0; - return result; - } - - protected override void OnFocusLost(InputState state) - { - if (state.Keyboard.Keys.Any(key => key == Key.Escape)) - { - if (Text.Length > 0) - Text = string.Empty; - else - Exit?.Invoke(); - } - base.OnFocusLost(state); - } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (HandlePendingText(state)) return true; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55eee483bdd7..42461d0bdd0f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -70,6 +70,7 @@ + From aac4ba2baacb78c2c998f98f23e3fa7f9e997176 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 18:02:25 +0900 Subject: [PATCH 04/18] Add input box to ChatOverlay. --- .../Online/Chat/Drawables/DrawableChannel.cs | 10 +++--- osu.Game/Overlays/ChatOverlay.cs | 34 +++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index d2968a732b72..07d56387666e 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -21,8 +21,8 @@ public class DrawableChannel : Container public DrawableChannel(Channel channel) { this.channel = channel; - newMessages(channel.Messages); - channel.NewMessagesArrived += newMessages; + newMessagesArrived(channel.Messages); + channel.NewMessagesArrived += newMessagesArrived; RelativeSizeAxes = Axes.Both; @@ -56,16 +56,16 @@ public DrawableChannel(Channel channel) protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - channel.NewMessagesArrived -= newMessages; + channel.NewMessagesArrived -= newMessagesArrived; } [BackgroundDependencyLoader] private void load() { - newMessages(channel.Messages); + newMessagesArrived(channel.Messages); } - private void newMessages(IEnumerable newMessages) + private void newMessagesArrived(IEnumerable newMessages) { if (!IsLoaded) return; diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index b9ac55bff076..3088b5e7a114 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -19,6 +19,10 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; using osu.Game.Online.Chat.Drawables; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Select; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Overlays { @@ -32,6 +36,8 @@ public class ChatOverlay : OverlayContainer, IOnlineComponent protected override Container Content => content; + private FocusedTextBox inputTextBox; + private APIAccess api; public ChatOverlay() @@ -52,10 +58,38 @@ public ChatOverlay() content = new Container { RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Bottom = 50 }, + }, + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 50, + Padding = new MarginPadding(5), + Children = new Drawable[] + { + inputTextBox = new FocusedTextBox + { + RelativeSizeAxes = Axes.X, + PlaceholderText = "type your message", + Exit = () => State = Visibility.Hidden, + OnCommit = postMessage, + HoldFocus = true, + } + } } }); } + private void postMessage(TextBox sender, bool newText) + { + var postText = sender.Text; + //todo: do something with postText. + + sender.Text = string.Empty; + } + [BackgroundDependencyLoader] private void load(APIAccess api) { From cde660a8efe801633cbf6df60f86ea6aa643b798 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 18:07:35 +0900 Subject: [PATCH 05/18] Scroll to bottom. --- osu.Game/Online/Chat/Drawables/DrawableChannel.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index 07d56387666e..e382b614524b 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -17,6 +17,7 @@ public class DrawableChannel : Container { private readonly Channel channel; private FlowContainer flow; + private ScrollContainer scroll; public DrawableChannel(Channel channel) { @@ -36,7 +37,7 @@ public DrawableChannel(Channel channel) Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new ScrollContainer + scroll = new ScrollContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -77,6 +78,8 @@ private void newMessagesArrived(IEnumerable newMessages) while (flow.Children.Count() > Channel.MAX_HISTORY) flow.Remove(flow.Children.First()); + + scroll.ScrollTo(flow.DrawHeight, false); } } } \ No newline at end of file From de87141e907672edf3531e51b561208e294c1909 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 18:39:54 +0900 Subject: [PATCH 06/18] Remove unused using statements. --- osu.Game/Overlays/ChatOverlay.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 3088b5e7a114..e1593f1654f9 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,12 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,7 +18,6 @@ using osu.Game.Online.Chat; using osu.Game.Online.Chat.Drawables; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens.Select; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; From c6fa5cc80393537788f8d919288f4bd7d3abb5d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 18:46:19 +0900 Subject: [PATCH 07/18] Fix order of execution when populating initial messages. --- osu.Game/Online/Chat/Drawables/DrawableChannel.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index e382b614524b..2042d7454bf9 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -22,8 +22,6 @@ public class DrawableChannel : Container public DrawableChannel(Channel channel) { this.channel = channel; - newMessagesArrived(channel.Messages); - channel.NewMessagesArrived += newMessagesArrived; RelativeSizeAxes = Axes.Both; @@ -52,6 +50,9 @@ public DrawableChannel(Channel channel) } } }; + + channel.NewMessagesArrived += newMessagesArrived; + newMessagesArrived(channel.Messages); } protected override void Dispose(bool isDisposing) @@ -60,12 +61,6 @@ protected override void Dispose(bool isDisposing) channel.NewMessagesArrived -= newMessagesArrived; } - [BackgroundDependencyLoader] - private void load() - { - newMessagesArrived(channel.Messages); - } - private void newMessagesArrived(IEnumerable newMessages) { if (!IsLoaded) return; From d13b82d073d1783ed180990adec9f8c1b71a9341 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Feb 2017 23:04:21 +0900 Subject: [PATCH 08/18] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 697d8b7e9530..1654acef1ca9 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 697d8b7e9530ba7914d9c78012329ce1559e3681 +Subproject commit 1654acef1ca9b9f203bfef1b507f3515b41a4d84 From 737bd62c30c6c1f2b29cf7d4e11a8f7c56bbfd27 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 15:27:48 +0900 Subject: [PATCH 09/18] Fix GlobalHotkeys not working (regression due to masking rules). --- osu.Game/Input/GlobalHotkeys.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Input/GlobalHotkeys.cs b/osu.Game/Input/GlobalHotkeys.cs index 96f8036aed51..b1b22f70696d 100644 --- a/osu.Game/Input/GlobalHotkeys.cs +++ b/osu.Game/Input/GlobalHotkeys.cs @@ -13,6 +13,11 @@ public class GlobalHotkeys : Drawable public override bool HandleInput => true; + public GlobalHotkeys() + { + RelativeSizeAxes = Axes.Both; + } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { return Handler(state, args); From 729f2eec8db0e220520b9bc081f26211fbd1a36c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:07:44 +0900 Subject: [PATCH 10/18] Increase maximum chat history. --- osu.Game/Online/Chat/Channel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index e67bfabc2e57..9060bcd4f161 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -30,7 +30,7 @@ public class Channel //internal bool Joined; - public const int MAX_HISTORY = 100; + public const int MAX_HISTORY = 300; [JsonConstructor] public Channel() From 7a2eedbd7eee0d75ff43c77a96db99fa55bdb47f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:09:34 +0900 Subject: [PATCH 11/18] Add message batching per-channel. --- osu.Game/Online/Chat/Channel.cs | 9 ++------- osu.Game/Overlays/ChatOverlay.cs | 9 +++++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 9060bcd4f161..d895b933363c 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -3,12 +3,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using Newtonsoft.Json; -using osu.Framework.Configuration; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; namespace osu.Game.Online.Chat { @@ -37,9 +32,9 @@ public Channel() { } - public event Action NewMessagesArrived; + public event Action> NewMessagesArrived; - public void AddNewMessages(params Message[] messages) + public void AddNewMessages(IEnumerable messages) { Messages.AddRange(messages); purgeOldMessages(); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index e1593f1654f9..40226eb1cf52 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -113,10 +113,11 @@ public void FetchNewMessages(APIAccess api) fetchReq = new GetMessagesRequest(careChannels, lastMessageId); fetchReq.Success += delegate (List messages) { - foreach (Message m in messages) - { - careChannels.Find(c => c.Id == m.ChannelId).AddNewMessages(m); - } + var ids = messages.Select(m => m.ChannelId).Distinct(); + + //batch messages per channel. + foreach (var id in ids) + careChannels.Find(c => c.Id == id)?.AddNewMessages(messages.Where(m => m.ChannelId == id)); lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId; From 75b66871dd65cefd29f510a9736f532b8e8f8cfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:09:56 +0900 Subject: [PATCH 12/18] Add colourised usernames. --- osu.Game/Online/Chat/Drawables/ChatLine.cs | 57 ++++++++++++++++++++-- osu.Game/Online/Chat/Message.cs | 1 + 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/Drawables/ChatLine.cs b/osu.Game/Online/Chat/Drawables/ChatLine.cs index 3780f6861556..7c6b079eb0b9 100644 --- a/osu.Game/Online/Chat/Drawables/ChatLine.cs +++ b/osu.Game/Online/Chat/Drawables/ChatLine.cs @@ -1,9 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -14,7 +17,51 @@ public class ChatLine : Container { public readonly Message Message; - const float padding = 250; + private static readonly Color4[] username_colours = { + OsuColour.FromHex("588c7e"), + OsuColour.FromHex("b2a367"), + OsuColour.FromHex("c98f65"), + OsuColour.FromHex("bc5151"), + OsuColour.FromHex("5c8bd6"), + OsuColour.FromHex("7f6ab7"), + OsuColour.FromHex("a368ad"), + OsuColour.FromHex("aa6880"), + + OsuColour.FromHex("6fad9b"), + OsuColour.FromHex("f2e394"), + OsuColour.FromHex("f2ae72"), + OsuColour.FromHex("f98f8a"), + OsuColour.FromHex("7daef4"), + OsuColour.FromHex("a691f2"), + OsuColour.FromHex("c894d3"), + OsuColour.FromHex("d895b0"), + + OsuColour.FromHex("53c4a1"), + OsuColour.FromHex("eace5c"), + OsuColour.FromHex("ea8c47"), + OsuColour.FromHex("fc4f4f"), + OsuColour.FromHex("3d94ea"), + OsuColour.FromHex("7760ea"), + OsuColour.FromHex("af52c6"), + OsuColour.FromHex("e25696"), + + OsuColour.FromHex("677c66"), + OsuColour.FromHex("9b8732"), + OsuColour.FromHex("8c5129"), + OsuColour.FromHex("8c3030"), + OsuColour.FromHex("1f5d91"), + OsuColour.FromHex("4335a5"), + OsuColour.FromHex("812a96"), + OsuColour.FromHex("992861"), + }; + + private Color4 getUsernameColour(Message message) + { + //todo: use User instead of Message when user_id is correctly populated. + return username_colours[message.UserId % username_colours.Length]; + } + + const float padding = 200; const float text_size = 20; public ChatLine(Message message) @@ -35,15 +82,19 @@ public ChatLine(Message message) { new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = @"Exo2.0-SemiBold", Text = $@"{Message.Timestamp.LocalDateTime:hh:mm:ss}", FixedWidth = true, - TextSize = text_size, - Colour = Color4.Gray + TextSize = text_size * 0.75f, + Alpha = 0.4f, }, new OsuSpriteText { Font = @"Exo2.0-BoldItalic", Text = $@"{Message.User.Name}:", + Colour = getUsernameColour(Message), TextSize = text_size, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index d412650176d2..3081653c346c 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -11,6 +11,7 @@ public class Message [JsonProperty(@"message_id")] public long Id; + //todo: this should be inside sender. [JsonProperty(@"user_id")] public int UserId; From 4afa434962ca08ab0be8730de65afd6389e9bc85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:10:23 +0900 Subject: [PATCH 13/18] Maintain a scroll position when scrolled to the bottom of a chat channel. --- .../Online/Chat/Drawables/DrawableChannel.cs | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index 2042d7454bf9..8697d2749e0d 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -52,7 +52,14 @@ public DrawableChannel(Channel channel) }; channel.NewMessagesArrived += newMessagesArrived; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + newMessagesArrived(channel.Messages); + scrollToEnd(); } protected override void Dispose(bool isDisposing) @@ -67,14 +74,25 @@ private void newMessagesArrived(IEnumerable newMessages) var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY)); + if (scroll.IsScrolledToEnd || !flow.Children.Any()) + scrollToEnd(); + //up to last Channel.MAX_HISTORY messages foreach (Message m in displayMessages) - flow.Add(new ChatLine(m)); - - while (flow.Children.Count() > Channel.MAX_HISTORY) - flow.Remove(flow.Children.First()); + { + var d = new ChatLine(m); + flow.Add(d); + } - scroll.ScrollTo(flow.DrawHeight, false); + while (flow.Children.Count(c => c.LifetimeEnd == double.MaxValue) > Channel.MAX_HISTORY) + { + var d = flow.Children.First(c => c.LifetimeEnd == double.MaxValue); + if (!scroll.IsScrolledToEnd) + scroll.OffsetScrollPosition(-d.DrawHeight); + d.Expire(); + } } + + private void scrollToEnd() => Scheduler.AddDelayed(() => scroll.ScrollToEnd(), 50); } } \ No newline at end of file From e3fa49dda7ad911731b08c71b1f2baa52f0d81a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:10:43 +0900 Subject: [PATCH 14/18] Naively "send" messages that the user types (doesn't arrive yet). --- osu.Game/Overlays/ChatOverlay.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 40226eb1cf52..b93acc46cbff 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -82,7 +82,20 @@ public ChatOverlay() private void postMessage(TextBox sender, bool newText) { var postText = sender.Text; - //todo: do something with postText. + + if (!string.IsNullOrEmpty(postText)) + { + //todo: actually send to server + careChannels.FirstOrDefault()?.AddNewMessages(new[] + { + new Message + { + User = api.LocalUser.Value, + Timestamp = DateTimeOffset.Now, + Content = postText + } + }); + } sender.Text = string.Empty; } From 6a836205891e7de103f23f3d8433d8cf3771eaf1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Feb 2017 21:11:09 +0900 Subject: [PATCH 15/18] Add better focus handling and padding/margin updates. --- .../Online/Chat/Drawables/DrawableChannel.cs | 7 ++++--- osu.Game/Overlays/ChatOverlay.cs | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index 8697d2749e0d..ef1e7ca5df85 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -4,10 +4,11 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Primitives; +using osu.Framework.MathUtils; +using osu.Framework.Threading; using osu.Game.Graphics.Sprites; using OpenTK; @@ -45,7 +46,7 @@ public DrawableChannel(Channel channel) Direction = FlowDirections.Vertical, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Spacing = new Vector2(1, 1) + Padding = new MarginPadding { Left = 20, Right = 20 } } } } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index b93acc46cbff..6bfd9730f0dd 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -20,10 +21,12 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; +using OpenTK.Graphics; +using osu.Framework.Input; namespace osu.Game.Overlays { - public class ChatOverlay : OverlayContainer, IOnlineComponent + public class ChatOverlay : FocusedOverlayContainer, IOnlineComponent { private DrawableChannel channelDisplay; @@ -50,7 +53,8 @@ public ChatOverlay() { Depth = float.MaxValue, RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.1f).Opacity(0.4f), + Colour = Color4.Black, + Alpha = 0.9f, }, content = new Container { @@ -62,13 +66,14 @@ public ChatOverlay() Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - Height = 50, + Height = 40, Padding = new MarginPadding(5), Children = new Drawable[] { inputTextBox = new FocusedTextBox { - RelativeSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, + Height = 1, PlaceholderText = "type your message", Exit = () => State = Visibility.Hidden, OnCommit = postMessage, @@ -79,6 +84,13 @@ public ChatOverlay() }); } + protected override bool OnFocus(InputState state) + { + //this is necessary as inputTextBox is masked away and therefore can't get focus :( + inputTextBox.TriggerFocus(); + return false; + } + private void postMessage(TextBox sender, bool newText) { var postText = sender.Text; From 5f29b0dc4f92dd3a5b8a757c2dce99e83dbaec26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Feb 2017 15:46:04 +0900 Subject: [PATCH 16/18] Update in line with framework changes. --- osu-framework | 2 +- osu.Game/Online/Chat/Drawables/DrawableChannel.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu-framework b/osu-framework index 1654acef1ca9..de1568254c4c 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1654acef1ca9b9f203bfef1b507f3515b41a4d84 +Subproject commit de1568254c4c9a4ea540ccad94700c5c51f70dc2 diff --git a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs index ef1e7ca5df85..5b8d034e9df7 100644 --- a/osu.Game/Online/Chat/Drawables/DrawableChannel.cs +++ b/osu.Game/Online/Chat/Drawables/DrawableChannel.cs @@ -75,7 +75,7 @@ private void newMessagesArrived(IEnumerable newMessages) var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY)); - if (scroll.IsScrolledToEnd || !flow.Children.Any()) + if (scroll.IsScrolledToEnd(10) || !flow.Children.Any()) scrollToEnd(); //up to last Channel.MAX_HISTORY messages @@ -88,7 +88,7 @@ private void newMessagesArrived(IEnumerable newMessages) while (flow.Children.Count(c => c.LifetimeEnd == double.MaxValue) > Channel.MAX_HISTORY) { var d = flow.Children.First(c => c.LifetimeEnd == double.MaxValue); - if (!scroll.IsScrolledToEnd) + if (!scroll.IsScrolledToEnd(10)) scroll.OffsetScrollPosition(-d.DrawHeight); d.Expire(); } From b7a9fd85eae6fdd36f071ff11df1b7385a5797b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2017 13:38:10 +0900 Subject: [PATCH 17/18] Assert single channel support for now. --- osu.Game/Overlays/ChatOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 6bfd9730f0dd..71fe754f77d2 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -208,6 +208,8 @@ private void initializeChannels() ListChannelsRequest req = new ListChannelsRequest(); req.Success += delegate (List channels) { + Debug.Assert(careChannels.Count == 0); + Scheduler.Add(delegate { loading.FadeOut(100); From 190bed893972180fa28777d986814901d4ff7036 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2017 13:38:22 +0900 Subject: [PATCH 18/18] Add top padding. --- osu.Game/Overlays/ChatOverlay.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 71fe754f77d2..e0e43fbe641e 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -28,6 +28,8 @@ namespace osu.Game.Overlays { public class ChatOverlay : FocusedOverlayContainer, IOnlineComponent { + const float textbox_height = 40; + private DrawableChannel channelDisplay; private ScheduledDelegate messageRequest; @@ -59,14 +61,14 @@ public ChatOverlay() content = new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Bottom = 50 }, + Padding = new MarginPadding { Top = 5, Bottom = textbox_height + 5 }, }, new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - Height = 40, + Height = textbox_height, Padding = new MarginPadding(5), Children = new Drawable[] {