mirror of
https://github.com/ppy/osu.git
synced 2025-02-22 16:03:21 +08:00
Improve robustness of chat auto-scrolling logic
Fix auto-scrolling state changing by old messages removal logic
This commit is contained in:
parent
39d46d21e6
commit
e806e5bcd1
@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
{
|
{
|
||||||
public readonly Channel Channel;
|
public readonly Channel Channel;
|
||||||
protected FillFlowContainer ChatLineFlow;
|
protected FillFlowContainer ChatLineFlow;
|
||||||
private OsuScrollContainer scroll;
|
private ChannelScrollContainer scroll;
|
||||||
|
|
||||||
private bool scrollbarVisible = true;
|
private bool scrollbarVisible = true;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Child = scroll = new OsuScrollContainer
|
Child = scroll = new ChannelScrollContainer
|
||||||
{
|
{
|
||||||
ScrollbarVisible = scrollbarVisible,
|
ScrollbarVisible = scrollbarVisible,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
@ -80,12 +80,6 @@ namespace osu.Game.Overlays.Chat
|
|||||||
Channel.PendingMessageResolved += pendingMessageResolved;
|
Channel.PendingMessageResolved += pendingMessageResolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
scrollToEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
@ -113,8 +107,6 @@ namespace osu.Game.Overlays.Chat
|
|||||||
ChatLineFlow.Clear();
|
ChatLineFlow.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldScrollToEnd = scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage);
|
|
||||||
|
|
||||||
// Add up to last Channel.MAX_HISTORY messages
|
// Add up to last Channel.MAX_HISTORY messages
|
||||||
var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY));
|
var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY));
|
||||||
|
|
||||||
@ -153,8 +145,10 @@ namespace osu.Game.Overlays.Chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldScrollToEnd)
|
// due to the scroll adjusts from old messages removal above, a scroll-to-end must be enforced,
|
||||||
scrollToEnd();
|
// to avoid making the container think the user has scrolled back up and unwantedly disable auto-scrolling.
|
||||||
|
if (scroll.ShouldAutoScroll || newMessages.Any(m => m is LocalMessage))
|
||||||
|
ScheduleAfterChildren(() => scroll.ScrollToEnd());
|
||||||
});
|
});
|
||||||
|
|
||||||
private void pendingMessageResolved(Message existing, Message updated) => Schedule(() =>
|
private void pendingMessageResolved(Message existing, Message updated) => Schedule(() =>
|
||||||
@ -178,8 +172,6 @@ namespace osu.Game.Overlays.Chat
|
|||||||
|
|
||||||
private IEnumerable<ChatLine> chatLines => ChatLineFlow.Children.OfType<ChatLine>();
|
private IEnumerable<ChatLine> chatLines => ChatLineFlow.Children.OfType<ChatLine>();
|
||||||
|
|
||||||
private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd());
|
|
||||||
|
|
||||||
public class DaySeparator : Container
|
public class DaySeparator : Container
|
||||||
{
|
{
|
||||||
public float TextSize
|
public float TextSize
|
||||||
@ -243,5 +235,32 @@ namespace osu.Game.Overlays.Chat
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="OsuScrollContainer"/> with functionality to automatically scrolls whenever the maximum scrollable distance increases.
|
||||||
|
/// </summary>
|
||||||
|
private class ChannelScrollContainer : OsuScrollContainer
|
||||||
|
{
|
||||||
|
private const float auto_scroll_leniency = 10f;
|
||||||
|
|
||||||
|
private float? lastExtent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this should automatically scroll to end on the next call to <see cref="UpdateAfterChildren"/>.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShouldAutoScroll { get; private set; } = true;
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
if ((lastExtent == null || ScrollableExtent > lastExtent) && ShouldAutoScroll)
|
||||||
|
ScrollToEnd();
|
||||||
|
else
|
||||||
|
ShouldAutoScroll = IsScrolledToEnd(auto_scroll_leniency);
|
||||||
|
|
||||||
|
lastExtent = ScrollableExtent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user