1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-14 07:24:04 +08:00

Compare commits

...

7 Commits

8 changed files with 174 additions and 44 deletions
+67 -2
View File
@@ -1,21 +1,86 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.ComponentModel;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.API;
using osu.Game.Online.Chat;
using osu.Game.Overlays;
using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
[Description("Testing chat api and overlay")]
public class TestCaseChatDisplay : OsuTestCase
{
public TestCaseChatDisplay()
private DummyChatOverlay chat;
private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) =>
dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
[BackgroundDependencyLoader]
private void load()
{
Add(new ChatOverlay
DummyAPIAccess api;
dependencies.CacheAs<IAPIProvider>(api = new DummyAPIAccess());
Add(chat = new DummyChatOverlay
{
State = Visibility.Visible
});
AddStep("Set Username DummyUser", () => api.LocalUser.Value.Username = "DummyUser");
AddStep("Type \"Hello\"", () => chat.PostMessage("Hello"));
AddStep("Set Long Username", () => api.LocalUser.Value.Username = "Over15LengthUserName");
AddStep("Type \"Over15LengthUserName\"", () => chat.PostMessage("Over15LengthUserName"));
AddStep("Set Wide Username", () => api.LocalUser.Value.Username = "WWWWWWWWWWWWWWW");
AddStep("Type \"Wide!\"", () => chat.PostMessage("Wide!"));
var channel = new Channel
{
Name = "#Dummy",
Topic = "Test Chat",
Type = "Test",
Id = 0
};
channel.AddNewMessages(
new DummyMessage("This message for test from offline."),
new DummyMessage("TestMessage"),
new DummyMessage("TestMessage"),
new DummyMessage("TestMessage")
);
chat.OpenChannel(channel);
}
private class DummyChatOverlay : ChatOverlay
{
public new void PostMessage(string postText) => base.PostMessage(postText);
}
private class DummyMessage : Message
{
private static long messageCounter;
public DummyMessage(string text, string username = null, bool isAction = false, bool isImportant = false, int number = 0)
: base(messageCounter++)
{
Content = text;
IsAction = isAction;
Timestamp = DateTimeOffset.Now;
Sender = new User
{
Username = username ?? $"User {number}",
Id = number,
Colour = isImportant ? "#250cc9" : null,
};
}
}
}
}
+2 -3
View File
@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Threading;
using osu.Framework;
using osu.Framework.Configuration;
using osu.Framework.Logging;
using osu.Framework.Threading;
@@ -16,7 +15,7 @@ using osu.Game.Users;
namespace osu.Game.Online.API
{
public class APIAccess : IUpdateable
public class APIAccess : IAPIProvider
{
private readonly OAuth authentication;
@@ -34,7 +33,7 @@ namespace osu.Game.Online.API
public string Password;
public Bindable<User> LocalUser = new Bindable<User>(createGuestUser());
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
public string Token
{
+28
View File
@@ -0,0 +1,28 @@
using osu.Framework.Configuration;
using osu.Game.Users;
namespace osu.Game.Online.API
{
public class DummyAPIAccess : IAPIProvider
{
public Bindable<User> LocalUser { get; } = new Bindable<User>(new User
{
Username = @"Dummy",
Id = 1,
});
public bool IsLoggedIn => true;
public void Update()
{
}
public virtual void Queue(APIRequest request)
{
}
public void Register(IOnlineComponent component)
{
}
}
}
+31
View File
@@ -0,0 +1,31 @@
using osu.Framework;
using osu.Framework.Configuration;
using osu.Game.Users;
namespace osu.Game.Online.API
{
public interface IAPIProvider : IUpdateable
{
/// <summary>
/// The local user.
/// </summary>
Bindable<User> LocalUser { get; }
/// <summary>
/// Returns whether the local user is logged in.
/// </summary>
bool IsLoggedIn { get; }
/// <summary>
/// Queue a new request.
/// </summary>
/// <param name="request">The request to perform.</param>
void Queue(APIRequest request);
/// <summary>
/// Register a component to receive state changes.
/// </summary>
/// <param name="component">The component to register.</param>
void Register(IOnlineComponent component);
}
}
+1
View File
@@ -105,6 +105,7 @@ namespace osu.Game
Username = LocalConfig.Get<string>(OsuSetting.Username),
Token = LocalConfig.Get<string>(OsuSetting.Token)
});
dependencies.CacheAs<IAPIProvider>(API);
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
+12 -3
View File
@@ -63,9 +63,10 @@ namespace osu.Game.Overlays.Chat
public const float LEFT_PADDING = message_padding + padding * 2;
private const float padding = 15;
private const float message_padding = 200;
private const float message_padding = 250;
private const float action_padding = 3;
private const float text_size = 20;
private const int max_username_length = 15;
private Color4 customUsernameColour;
@@ -87,6 +88,8 @@ namespace osu.Game.Overlays.Chat
public LinkFlowContainer ContentFlow => contentFlow;
private ChatOverlay chat;
public Message Message
{
get => message;
@@ -123,6 +126,7 @@ namespace osu.Game.Overlays.Chat
Font = @"Exo2.0-BoldItalic",
Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length],
TextSize = text_size,
FixedWidth = true,
};
if (hasBackground)
@@ -215,7 +219,12 @@ namespace osu.Game.Overlays.Chat
FinishTransforms(true);
}
private ChatOverlay chat;
private string normalizeUsername(string usernameText)
{
if(usernameText.Length <= max_username_length)
return usernameText;
return usernameText.Substring(0, max_username_length - 3) + "...";
}
private void updateMessageContent()
{
@@ -223,7 +232,7 @@ namespace osu.Game.Overlays.Chat
timestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint);
timestamp.Text = $@"{message.Timestamp.LocalDateTime:HH:mm:ss}";
username.Text = $@"{message.Sender.Username}" + (senderHasBackground || message.IsAction ? "" : ":");
username.Text = $@"{normalizeUsername(message.Sender.Username)}" + (senderHasBackground || message.IsAction ? "" : ":");
// remove non-existent channels from the link list
message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chat?.AvailableChannels.Any(c => c.Name == link.Argument) != true);
+31 -36
View File
@@ -39,9 +39,9 @@ namespace osu.Game.Overlays
private readonly LoadingAnimation loading;
private readonly FocusedTextBox textbox;
protected readonly FocusedTextBox Textbox;
private APIAccess api;
protected IAPIProvider Api;
private const int transition_length = 500;
@@ -64,7 +64,8 @@ namespace osu.Game.Overlays
private readonly Container channelSelectionContainer;
private readonly ChannelSelectionOverlay channelSelection;
public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceiveMouseInputAt(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.ReceiveMouseInputAt(screenSpacePos);
public override bool Contains(Vector2 screenSpacePos) =>
chatContainer.ReceiveMouseInputAt(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.ReceiveMouseInputAt(screenSpacePos);
public ChatOverlay()
{
@@ -133,13 +134,13 @@ namespace osu.Game.Overlays
},
Children = new Drawable[]
{
textbox = new FocusedTextBox
Textbox = new FocusedTextBox
{
RelativeSizeAxes = Axes.Both,
Height = 1,
PlaceholderText = "type your message",
Exit = () => State = Visibility.Hidden,
OnCommit = postMessage,
OnCommit = handleTextboxMessage,
ReleaseFocusOnCommit = false,
HoldFocus = true,
}
@@ -179,12 +180,12 @@ namespace osu.Game.Overlays
if (state == Visibility.Visible)
{
textbox.HoldFocus = false;
Textbox.HoldFocus = false;
if (1f - ChatHeight.Value < channel_selection_min_height)
transformChatHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint);
}
else
textbox.HoldFocus = true;
Textbox.HoldFocus = true;
};
}
@@ -246,7 +247,7 @@ namespace osu.Game.Overlays
protected override void OnFocus(InputState state)
{
//this is necessary as textbox is masked away and therefore can't get focus :(
GetContainingInputManager().ChangeFocus(textbox);
GetContainingInputManager().ChangeFocus(Textbox);
base.OnFocus(state);
}
@@ -255,7 +256,7 @@ namespace osu.Game.Overlays
this.MoveToY(0, transition_length, Easing.OutQuint);
this.FadeIn(transition_length, Easing.OutQuint);
textbox.HoldFocus = true;
Textbox.HoldFocus = true;
base.PopIn();
}
@@ -264,14 +265,14 @@ namespace osu.Game.Overlays
this.MoveToY(Height, transition_length, Easing.InSine);
this.FadeOut(transition_length, Easing.InSine);
textbox.HoldFocus = false;
Textbox.HoldFocus = false;
base.PopOut();
}
[BackgroundDependencyLoader]
private void load(APIAccess api, OsuConfigManager config, OsuColour colours)
private void load(IAPIProvider api, OsuConfigManager config, OsuColour colours)
{
this.api = api;
Api = api;
api.Register(this);
ChatHeight = config.GetBindable<double>(OsuSetting.ChatDisplayHeight);
@@ -299,7 +300,7 @@ namespace osu.Game.Overlays
messageRequest?.Cancel();
ListChannelsRequest req = new ListChannelsRequest();
req.Success += delegate (List<Channel> channels)
req.Success += delegate(List<Channel> channels)
{
AvailableChannels = channels;
@@ -324,17 +325,14 @@ namespace osu.Game.Overlays
messageRequest = Scheduler.AddDelayed(fetchNewMessages, 1000, true);
};
api.Queue(req);
Api.Queue(req);
}
private Channel currentChannel;
protected Channel CurrentChannel
{
get
{
return currentChannel;
}
get { return currentChannel; }
set
{
@@ -343,14 +341,14 @@ namespace osu.Game.Overlays
if (value == null)
{
currentChannel = null;
textbox.Current.Disabled = true;
Textbox.Current.Disabled = true;
currentChannelContainer.Clear(false);
return;
}
currentChannel = value;
textbox.Current.Disabled = currentChannel.ReadOnly;
Textbox.Current.Disabled = currentChannel.ReadOnly;
channelTabs.Current.Value = value;
var loaded = loadedChannels.Find(d => d.Channel == value);
@@ -422,18 +420,15 @@ namespace osu.Game.Overlays
{
var req = new GetMessagesRequest(new List<Channel> { channel }, null);
req.Success += delegate (List<Message> messages)
req.Success += delegate(List<Message> messages)
{
loading.Hide();
channel.AddNewMessages(messages.ToArray());
Debug.Write("success!");
};
req.Failure += delegate
{
Debug.Write("failure!");
};
req.Failure += delegate { Debug.Write("failure!"); };
api.Queue(req);
Api.Queue(req);
}
private void fetchNewMessages()
@@ -442,32 +437,32 @@ namespace osu.Game.Overlays
fetchReq = new GetMessagesRequest(careChannels, lastMessageId);
fetchReq.Success += delegate (List<Message> messages)
fetchReq.Success += delegate(List<Message> messages)
{
foreach (var group in messages.Where(m => m.TargetType == TargetType.Channel).GroupBy(m => m.TargetId))
careChannels.Find(c => c.Id == group.Key)?.AddNewMessages(group.ToArray());
lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId;
Debug.Write("success!");
fetchReq = null;
};
fetchReq.Failure += delegate
{
Debug.Write("failure!");
fetchReq = null;
};
api.Queue(fetchReq);
Api.Queue(fetchReq);
}
private void postMessage(TextBox textbox, bool newText)
private void handleTextboxMessage(TextBox textbox, bool newText)
{
var postText = textbox.Text;
textbox.Text = string.Empty;
PostMessage(postText);
}
protected void PostMessage(string postText)
{
if (string.IsNullOrWhiteSpace(postText))
return;
@@ -475,7 +470,7 @@ namespace osu.Game.Overlays
if (target == null) return;
if (!api.IsLoggedIn)
if (!Api.IsLoggedIn)
{
target.AddNewMessages(new ErrorMessage("Please login to participate in chat!"));
return;
@@ -515,7 +510,7 @@ namespace osu.Game.Overlays
var message = new LocalEchoMessage
{
Sender = api.LocalUser.Value,
Sender = Api.LocalUser.Value,
Timestamp = DateTimeOffset.Now,
TargetType = TargetType.Channel, //TODO: read this from channel
TargetId = target.Id,
@@ -529,7 +524,7 @@ namespace osu.Game.Overlays
req.Failure += e => target.ReplaceMessage(message, null);
req.Success += m => target.ReplaceMessage(message, m);
api.Queue(req);
Api.Queue(req);
}
private void transformChatHeightTo(double newChatHeight, double duration = 0, Easing easing = Easing.None)
+2
View File
@@ -281,6 +281,8 @@
<Compile Include="Database\SingletonContextFactory.cs" />
<Compile Include="Graphics\Containers\LinkFlowContainer.cs" />
<Compile Include="Graphics\Textures\LargeTextureStore.cs" />
<Compile Include="Online\API\DummyAPIAccess.cs" />
<Compile Include="Online\API\IAPIProvider.cs" />
<Compile Include="Online\API\Requests\GetUserRequest.cs" />
<Compile Include="Migrations\20180125143340_Settings.cs" />
<Compile Include="Migrations\20180125143340_Settings.Designer.cs">