mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 15:44:04 +09:00
Merge remote-tracking branch 'upstream/master' into chat-mention
This commit is contained in:
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Chat.Tabs;
|
||||
@ -33,6 +34,16 @@ namespace osu.Game.Online.Chat
|
||||
private readonly BindableList<Channel> availableChannels = new BindableList<Channel>();
|
||||
private readonly BindableList<Channel> joinedChannels = new BindableList<Channel>();
|
||||
|
||||
/// <summary>
|
||||
/// Keeps a stack of recently closed channels
|
||||
/// </summary>
|
||||
private readonly List<ClosedChannel> closedChannels = new List<ClosedChannel>();
|
||||
|
||||
// For efficiency purposes, this constant bounds the number of closed channels we store.
|
||||
// This number is somewhat arbitrary; future developers are free to modify it.
|
||||
// Must be a positive number.
|
||||
private const int closed_channels_max_size = 50;
|
||||
|
||||
/// <summary>
|
||||
/// The currently opened channel
|
||||
/// </summary>
|
||||
@ -51,6 +62,9 @@ namespace osu.Game.Online.Chat
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private UserLookupCache users { get; set; }
|
||||
|
||||
public readonly BindableBool HighPollRate = new BindableBool();
|
||||
|
||||
public ChannelManager()
|
||||
@ -420,6 +434,18 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
joinedChannels.Remove(channel);
|
||||
|
||||
// Prevent the closedChannel list from exceeding the max size
|
||||
// by removing the oldest element
|
||||
if (closedChannels.Count >= closed_channels_max_size)
|
||||
{
|
||||
closedChannels.RemoveAt(0);
|
||||
}
|
||||
|
||||
// For PM channels, we store the user ID; else, we store the channel ID
|
||||
closedChannels.Add(channel.Type == ChannelType.PM
|
||||
? new ClosedChannel(ChannelType.PM, channel.Users.Single().Id)
|
||||
: new ClosedChannel(channel.Type, channel.Id));
|
||||
|
||||
if (channel.Joined.Value)
|
||||
{
|
||||
api.Queue(new LeaveChannelRequest(channel));
|
||||
@ -427,6 +453,46 @@ namespace osu.Game.Online.Chat
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Opens the most recently closed channel that has not already been reopened,
|
||||
/// Works similarly to reopening the last closed tab on a web browser.
|
||||
/// </summary>
|
||||
public void JoinLastClosedChannel()
|
||||
{
|
||||
// This loop could be eliminated if the join channel operation ensured that every channel joined
|
||||
// is removed from the closedChannels list, but it'd require a linear scan of closed channels on every join.
|
||||
// To keep the overhead of joining channels low, just lazily scan the list of closed channels locally.
|
||||
while (closedChannels.Count > 0)
|
||||
{
|
||||
ClosedChannel lastClosedChannel = closedChannels.Last();
|
||||
closedChannels.RemoveAt(closedChannels.Count - 1);
|
||||
|
||||
// If the user has already joined the channel, try the next one
|
||||
if (joinedChannels.FirstOrDefault(lastClosedChannel.Matches) != null)
|
||||
continue;
|
||||
|
||||
Channel lastChannel = AvailableChannels.FirstOrDefault(lastClosedChannel.Matches);
|
||||
|
||||
if (lastChannel != null)
|
||||
{
|
||||
// Channel exists as an available channel, directly join it
|
||||
CurrentChannel.Value = JoinChannel(lastChannel);
|
||||
}
|
||||
else if (lastClosedChannel.Type == ChannelType.PM)
|
||||
{
|
||||
// Try to get user in order to open PM chat
|
||||
users.GetUserAsync((int)lastClosedChannel.Id).ContinueWith(u =>
|
||||
{
|
||||
if (u.Result == null) return;
|
||||
|
||||
Schedule(() => CurrentChannel.Value = JoinChannel(new Channel(u.Result)));
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private long lastMessageId;
|
||||
|
||||
private bool channelsInitialised;
|
||||
@ -511,4 +577,28 @@ namespace osu.Game.Online.Chat
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores information about a closed channel
|
||||
/// </summary>
|
||||
public class ClosedChannel
|
||||
{
|
||||
public readonly ChannelType Type;
|
||||
public readonly long Id;
|
||||
|
||||
public ClosedChannel(ChannelType type, long id)
|
||||
{
|
||||
Type = type;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public bool Matches(Channel channel)
|
||||
{
|
||||
if (channel.Type != Type) return false;
|
||||
|
||||
return Type == ChannelType.PM
|
||||
? channel.Users.Single().Id == Id
|
||||
: channel.Id == Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace osu.Game.Online.Chat
|
||||
{
|
||||
public static class MessageFormatter
|
||||
@ -61,7 +63,7 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
private static string websiteRootUrl = "osu.ppy.sh";
|
||||
|
||||
private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null, char[] escapeChars = null)
|
||||
private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null, char[]? escapeChars = null)
|
||||
{
|
||||
int captureOffset = 0;
|
||||
|
||||
@ -167,15 +169,18 @@ namespace osu.Game.Online.Chat
|
||||
case "u":
|
||||
case "users":
|
||||
return new LinkDetails(LinkAction.OpenUserProfile, mainArg);
|
||||
|
||||
case "wiki":
|
||||
return new LinkDetails(LinkAction.OpenWiki, string.Join('/', args.Skip(3)));
|
||||
}
|
||||
}
|
||||
|
||||
return new LinkDetails(LinkAction.External, null);
|
||||
break;
|
||||
|
||||
case "osu":
|
||||
// every internal link also needs some kind of argument
|
||||
if (args.Length < 3)
|
||||
return new LinkDetails(LinkAction.External, null);
|
||||
break;
|
||||
|
||||
LinkAction linkType;
|
||||
|
||||
@ -217,7 +222,7 @@ namespace osu.Game.Online.Chat
|
||||
return new LinkDetails(LinkAction.JoinMultiplayerMatch, args[1]);
|
||||
}
|
||||
|
||||
return new LinkDetails(LinkAction.External, null);
|
||||
return new LinkDetails(LinkAction.External, url);
|
||||
}
|
||||
|
||||
private static MessageFormatterResult format(string toFormat, int startIndex = 0, int space = 3)
|
||||
@ -311,7 +316,8 @@ namespace osu.Game.Online.Chat
|
||||
JoinMultiplayerMatch,
|
||||
Spectate,
|
||||
OpenUserProfile,
|
||||
Custom
|
||||
OpenWiki,
|
||||
Custom,
|
||||
}
|
||||
|
||||
public class Link : IComparable<Link>
|
||||
|
Reference in New Issue
Block a user