1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-23 12:07:25 +08:00
osu-lazer/osu.Game/Online/Chat/StandAloneChatDisplay.cs
Jai Sharma c0aaeff2b3 Update DaySeparator to use new design throughout
Moves `DaySeparator` chat component to it's own file and update it to
match new chat design. Makes use of several virtual attributes that can
be overridden to update spacing and layout in other usage contexts.

Remove redundant usage of `ChatOverlayDaySeparator`, since the new
design is now part of the base class.

Create `StandAloneDaySeparator` to use in `StandAloneChatDisplay` which
overrides attributes to match correct spacing and layout for its design.

Ensure that `DrawableChannel.CreateDaySeparator` returns type of
`DaySeparator` instead of `Drawable`.
2022-06-04 18:02:14 +01:00

211 lines
6.6 KiB
C#

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Chat;
using osu.Game.Resources.Localisation.Web;
using osuTK.Graphics;
using osuTK.Input;
namespace osu.Game.Online.Chat
{
/// <summary>
/// Display a chat channel in an insolated region.
/// </summary>
public class StandAloneChatDisplay : CompositeDrawable
{
public readonly Bindable<Channel> Channel = new Bindable<Channel>();
protected readonly ChatTextBox TextBox;
private ChannelManager channelManager;
private StandAloneDrawableChannel drawableChannel;
private readonly bool postingTextBox;
protected readonly Box Background;
private const float text_box_height = 30;
/// <summary>
/// Construct a new instance.
/// </summary>
/// <param name="postingTextBox">Whether a textbox for posting new messages should be displayed.</param>
public StandAloneChatDisplay(bool postingTextBox = false)
{
const float corner_radius = 10;
this.postingTextBox = postingTextBox;
CornerRadius = corner_radius;
Masking = true;
InternalChildren = new Drawable[]
{
Background = new Box
{
Colour = Color4.Black,
Alpha = 0.8f,
RelativeSizeAxes = Axes.Both
},
};
if (postingTextBox)
{
AddInternal(TextBox = new ChatTextBox
{
RelativeSizeAxes = Axes.X,
Height = text_box_height,
PlaceholderText = ChatStrings.InputPlaceholder,
CornerRadius = corner_radius,
ReleaseFocusOnCommit = false,
HoldFocus = true,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
});
TextBox.OnCommit += postMessage;
}
Channel.BindValueChanged(channelChanged);
}
[BackgroundDependencyLoader(true)]
private void load(ChannelManager manager)
{
channelManager ??= manager;
}
protected virtual StandAloneDrawableChannel CreateDrawableChannel(Channel channel) =>
new StandAloneDrawableChannel(channel);
private void postMessage(TextBox sender, bool newText)
{
string text = TextBox.Text.Trim();
if (string.IsNullOrWhiteSpace(text))
return;
if (text[0] == '/')
channelManager?.PostCommand(text.Substring(1), Channel.Value);
else
channelManager?.PostMessage(text, target: Channel.Value);
TextBox.Text = string.Empty;
}
protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message);
private void channelChanged(ValueChangedEvent<Channel> e)
{
drawableChannel?.Expire();
if (e.NewValue == null) return;
drawableChannel = CreateDrawableChannel(e.NewValue);
drawableChannel.CreateChatLineAction = CreateMessage;
drawableChannel.Padding = new MarginPadding { Bottom = postingTextBox ? text_box_height : 0 };
AddInternal(drawableChannel);
}
public class ChatTextBox : FocusedTextBox
{
protected override bool OnKeyDown(KeyDownEvent e)
{
// Chat text boxes are generally used in places where they retain focus, but shouldn't block interaction with other
// elements on the same screen.
switch (e.Key)
{
case Key.Up:
case Key.Down:
return false;
}
return base.OnKeyDown(e);
}
protected override void LoadComplete()
{
base.LoadComplete();
BackgroundUnfocused = new Color4(10, 10, 10, 10);
BackgroundFocused = new Color4(10, 10, 10, 255);
}
protected override void OnFocusLost(FocusLostEvent e)
{
base.OnFocusLost(e);
FocusLost?.Invoke();
}
public Action FocusLost;
}
public class StandAloneDrawableChannel : DrawableChannel
{
public Func<Message, ChatLine> CreateChatLineAction;
public StandAloneDrawableChannel(Channel channel)
: base(channel)
{
}
[BackgroundDependencyLoader]
private void load()
{
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
ChatLineFlow.Padding = new MarginPadding { Horizontal = 0 };
}
protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m);
protected override DaySeparator CreateDaySeparator(DateTimeOffset time) => new StandAloneDaySeparator(time);
}
protected class StandAloneDaySeparator : DaySeparator
{
protected override float TextSize => 14;
protected override float LineHeight => 1;
protected override float Spacing => 10;
protected override float DateAlign => 120;
public StandAloneDaySeparator(DateTimeOffset time)
: base(time)
{
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Height = 25;
Colour = colours.Yellow;
// TODO: Remove once DrawableChannel & ChatLine padding is fixed
Padding = new MarginPadding { Horizontal = 10 };
}
}
protected class StandAloneMessage : ChatLine
{
protected override float TextSize => 15;
protected override float HorizontalPadding => 10;
protected override float MessagePadding => 120;
protected override float TimestampPadding => 50;
public StandAloneMessage(Message message)
: base(message)
{
}
}
}
}