mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 00:12:59 +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;
|
||||
protected FillFlowContainer ChatLineFlow;
|
||||
private OsuScrollContainer scroll;
|
||||
private ChannelScrollContainer scroll;
|
||||
|
||||
private bool scrollbarVisible = true;
|
||||
|
||||
@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Chat
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Child = scroll = new OsuScrollContainer
|
||||
Child = scroll = new ChannelScrollContainer
|
||||
{
|
||||
ScrollbarVisible = scrollbarVisible,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -80,12 +80,6 @@ namespace osu.Game.Overlays.Chat
|
||||
Channel.PendingMessageResolved += pendingMessageResolved;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
scrollToEnd();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
@ -113,8 +107,6 @@ namespace osu.Game.Overlays.Chat
|
||||
ChatLineFlow.Clear();
|
||||
}
|
||||
|
||||
bool shouldScrollToEnd = scroll.IsScrolledToEnd(10) || !chatLines.Any() || newMessages.Any(m => m is LocalMessage);
|
||||
|
||||
// Add up to last Channel.MAX_HISTORY messages
|
||||
var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY));
|
||||
|
||||
@ -153,8 +145,10 @@ namespace osu.Game.Overlays.Chat
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldScrollToEnd)
|
||||
scrollToEnd();
|
||||
// due to the scroll adjusts from old messages removal above, a scroll-to-end must be enforced,
|
||||
// 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(() =>
|
||||
@ -178,8 +172,6 @@ namespace osu.Game.Overlays.Chat
|
||||
|
||||
private IEnumerable<ChatLine> chatLines => ChatLineFlow.Children.OfType<ChatLine>();
|
||||
|
||||
private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd());
|
||||
|
||||
public class DaySeparator : Container
|
||||
{
|
||||
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