mirror of
https://github.com/ppy/osu
synced 2024-12-16 20:05:41 +00:00
Merge branch 'master' into first-run-setup
This commit is contained in:
commit
d17c16d904
110
.github/workflows/ci.yml
vendored
110
.github/workflows/ci.yml
vendored
@ -2,6 +2,60 @@ on: [push, pull_request]
|
|||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
inspect-code:
|
||||||
|
name: Code Quality
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side.
|
||||||
|
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
||||||
|
- name: Install .NET 3.1.x LTS
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: "3.1.x"
|
||||||
|
|
||||||
|
- name: Install .NET 6.0.x
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
|
- name: Restore Tools
|
||||||
|
run: dotnet tool restore
|
||||||
|
|
||||||
|
- name: Restore Packages
|
||||||
|
run: dotnet restore
|
||||||
|
|
||||||
|
- name: Restore inspectcode cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/inspectcode
|
||||||
|
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json') }}-${{ hashFiles('.github/workflows/ci.yml' ) }}
|
||||||
|
|
||||||
|
- name: CodeFileSanity
|
||||||
|
run: |
|
||||||
|
# TODO: Add ignore filters and GitHub Workflow Command Reporting in CFS. That way we don't have to do this workaround.
|
||||||
|
# FIXME: Suppress warnings from templates project
|
||||||
|
exit_code=0
|
||||||
|
while read -r line; do
|
||||||
|
if [[ ! -z "$line" ]]; then
|
||||||
|
echo "::error::$line"
|
||||||
|
exit_code=1
|
||||||
|
fi
|
||||||
|
done <<< $(dotnet codefilesanity)
|
||||||
|
exit $exit_code
|
||||||
|
|
||||||
|
# Temporarily disabled due to test failures, but it won't work anyway until the tool is upgraded.
|
||||||
|
# - name: .NET Format (Dry Run)
|
||||||
|
# run: dotnet format --dry-run --check
|
||||||
|
|
||||||
|
- name: InspectCode
|
||||||
|
run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN
|
||||||
|
|
||||||
|
- name: NVika
|
||||||
|
run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
runs-on: ${{matrix.os.fullname}}
|
runs-on: ${{matrix.os.fullname}}
|
||||||
@ -93,58 +147,4 @@ jobs:
|
|||||||
# cannot accept .sln(f) files as arguments.
|
# cannot accept .sln(f) files as arguments.
|
||||||
# Build just the main game for now.
|
# Build just the main game for now.
|
||||||
- name: Build
|
- name: Build
|
||||||
run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug
|
run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug
|
||||||
|
|
||||||
inspect-code:
|
|
||||||
name: Code Quality
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side.
|
|
||||||
# https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
|
|
||||||
- name: Install .NET 3.1.x LTS
|
|
||||||
uses: actions/setup-dotnet@v1
|
|
||||||
with:
|
|
||||||
dotnet-version: "3.1.x"
|
|
||||||
|
|
||||||
- name: Install .NET 6.0.x
|
|
||||||
uses: actions/setup-dotnet@v1
|
|
||||||
with:
|
|
||||||
dotnet-version: "6.0.x"
|
|
||||||
|
|
||||||
- name: Restore Tools
|
|
||||||
run: dotnet tool restore
|
|
||||||
|
|
||||||
- name: Restore Packages
|
|
||||||
run: dotnet restore
|
|
||||||
|
|
||||||
- name: Restore inspectcode cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/inspectcode
|
|
||||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json') }}-${{ hashFiles('.github/workflows/ci.yml' ) }}
|
|
||||||
|
|
||||||
- name: CodeFileSanity
|
|
||||||
run: |
|
|
||||||
# TODO: Add ignore filters and GitHub Workflow Command Reporting in CFS. That way we don't have to do this workaround.
|
|
||||||
# FIXME: Suppress warnings from templates project
|
|
||||||
exit_code=0
|
|
||||||
while read -r line; do
|
|
||||||
if [[ ! -z "$line" ]]; then
|
|
||||||
echo "::error::$line"
|
|
||||||
exit_code=1
|
|
||||||
fi
|
|
||||||
done <<< $(dotnet codefilesanity)
|
|
||||||
exit $exit_code
|
|
||||||
|
|
||||||
# Temporarily disabled due to test failures, but it won't work anyway until the tool is upgraded.
|
|
||||||
# - name: .NET Format (Dry Run)
|
|
||||||
# run: dotnet format --dry-run --check
|
|
||||||
|
|
||||||
- name: InspectCode
|
|
||||||
run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN
|
|
||||||
|
|
||||||
- name: NVika
|
|
||||||
run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors
|
|
188
osu.Game.Tests/Visual/Online/TestSceneChannelList.cs
Normal file
188
osu.Game.Tests/Visual/Online/TestSceneChannelList.cs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Online.Chat;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.Chat.ChannelList;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneChannelList : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly Bindable<Channel> selected = new Bindable<Channel>();
|
||||||
|
|
||||||
|
private OsuSpriteText selectorText;
|
||||||
|
private OsuSpriteText selectedText;
|
||||||
|
private OsuSpriteText leaveText;
|
||||||
|
private ChannelList channelList;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
Schedule(() =>
|
||||||
|
{
|
||||||
|
Child = new GridContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Height = 0.7f,
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.Absolute, 20),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 20),
|
||||||
|
new Dimension(GridSizeMode.Absolute, 20),
|
||||||
|
new Dimension(),
|
||||||
|
},
|
||||||
|
Content = new[]
|
||||||
|
{
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
selectorText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
selectedText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
leaveText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new Drawable[]
|
||||||
|
{
|
||||||
|
channelList = new ChannelList
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 190,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
channelList.OnRequestSelect += channel =>
|
||||||
|
{
|
||||||
|
channelList.SelectorActive.Value = false;
|
||||||
|
selected.Value = channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
channelList.OnRequestLeave += channel =>
|
||||||
|
{
|
||||||
|
leaveText.Text = $"OnRequestLeave: {channel.Name}";
|
||||||
|
leaveText.FadeOutFromOne(1000, Easing.InQuint);
|
||||||
|
selected.Value = null;
|
||||||
|
channelList.RemoveChannel(channel);
|
||||||
|
};
|
||||||
|
|
||||||
|
channelList.SelectorActive.BindValueChanged(change =>
|
||||||
|
{
|
||||||
|
selectorText.Text = $"Channel Selector Active: {change.NewValue}";
|
||||||
|
selected.Value = null;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
selected.BindValueChanged(change =>
|
||||||
|
{
|
||||||
|
selectedText.Text = $"Selected Channel: {change.NewValue?.Name ?? "[null]"}";
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("Add Public Channels", () =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
channelList.AddChannel(createRandomPublicChannel());
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Add Private Channels", () =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
channelList.AddChannel(createRandomPrivateChannel());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestVisual()
|
||||||
|
{
|
||||||
|
AddStep("Unread Selected", () =>
|
||||||
|
{
|
||||||
|
if (selected.Value != null)
|
||||||
|
channelList.GetItem(selected.Value).Unread.Value = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Read Selected", () =>
|
||||||
|
{
|
||||||
|
if (selected.Value != null)
|
||||||
|
channelList.GetItem(selected.Value).Unread.Value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Add Mention Selected", () =>
|
||||||
|
{
|
||||||
|
if (selected.Value != null)
|
||||||
|
channelList.GetItem(selected.Value).Mentions.Value++;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Add 98 Mentions Selected", () =>
|
||||||
|
{
|
||||||
|
if (selected.Value != null)
|
||||||
|
channelList.GetItem(selected.Value).Mentions.Value += 98;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Clear Mentions Selected", () =>
|
||||||
|
{
|
||||||
|
if (selected.Value != null)
|
||||||
|
channelList.GetItem(selected.Value).Mentions.Value = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Channel createRandomPublicChannel()
|
||||||
|
{
|
||||||
|
int id = RNG.Next(0, 10000);
|
||||||
|
return new Channel
|
||||||
|
{
|
||||||
|
Name = $"#channel-{id}",
|
||||||
|
Type = ChannelType.Public,
|
||||||
|
Id = id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Channel createRandomPrivateChannel()
|
||||||
|
{
|
||||||
|
int id = RNG.Next(0, 10000);
|
||||||
|
return new Channel(new APIUser
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Username = $"test user {id}",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,163 +0,0 @@
|
|||||||
// 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 NUnit.Framework;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Online.Chat;
|
|
||||||
using osu.Game.Overlays;
|
|
||||||
using osu.Game.Overlays.Chat.ChannelList;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TestSceneChannelListItem : OsuTestScene
|
|
||||||
{
|
|
||||||
[Cached]
|
|
||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
|
||||||
|
|
||||||
[Cached]
|
|
||||||
private readonly Bindable<Channel> selected = new Bindable<Channel>();
|
|
||||||
|
|
||||||
private static readonly List<Channel> channels = new List<Channel>
|
|
||||||
{
|
|
||||||
createPublicChannel("#public-channel"),
|
|
||||||
createPublicChannel("#public-channel-long-name"),
|
|
||||||
createPrivateChannel("test user", 2),
|
|
||||||
createPrivateChannel("test user long name", 3),
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly Dictionary<Channel, ChannelListItem> channelMap = new Dictionary<Channel, ChannelListItem>();
|
|
||||||
|
|
||||||
private FillFlowContainer flow;
|
|
||||||
private OsuSpriteText selectedText;
|
|
||||||
private OsuSpriteText leaveText;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
Schedule(() =>
|
|
||||||
{
|
|
||||||
foreach (var item in channelMap.Values)
|
|
||||||
item.Expire();
|
|
||||||
|
|
||||||
channelMap.Clear();
|
|
||||||
|
|
||||||
Child = new FillFlowContainer
|
|
||||||
{
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Spacing = new Vector2(10),
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
selectedText = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
leaveText = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Height = 16,
|
|
||||||
AlwaysPresent = true,
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Width = 190,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = colourProvider.Background6,
|
|
||||||
},
|
|
||||||
flow = new FillFlowContainer
|
|
||||||
{
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
selected.BindValueChanged(change =>
|
|
||||||
{
|
|
||||||
selectedText.Text = $"Selected Channel: {change.NewValue?.Name ?? "[null]"}";
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
foreach (var channel in channels)
|
|
||||||
{
|
|
||||||
var item = new ChannelListItem(channel);
|
|
||||||
flow.Add(item);
|
|
||||||
channelMap.Add(channel, item);
|
|
||||||
item.OnRequestSelect += c => selected.Value = c;
|
|
||||||
item.OnRequestLeave += leaveChannel;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestVisual()
|
|
||||||
{
|
|
||||||
AddStep("Select second item", () => selected.Value = channels.Skip(1).First());
|
|
||||||
|
|
||||||
AddStep("Unread Selected", () =>
|
|
||||||
{
|
|
||||||
if (selected.Value != null)
|
|
||||||
channelMap[selected.Value].Unread.Value = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("Read Selected", () =>
|
|
||||||
{
|
|
||||||
if (selected.Value != null)
|
|
||||||
channelMap[selected.Value].Unread.Value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("Add Mention Selected", () =>
|
|
||||||
{
|
|
||||||
if (selected.Value != null)
|
|
||||||
channelMap[selected.Value].Mentions.Value++;
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("Add 98 Mentions Selected", () =>
|
|
||||||
{
|
|
||||||
if (selected.Value != null)
|
|
||||||
channelMap[selected.Value].Mentions.Value += 98;
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("Clear Mentions Selected", () =>
|
|
||||||
{
|
|
||||||
if (selected.Value != null)
|
|
||||||
channelMap[selected.Value].Mentions.Value = 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void leaveChannel(Channel channel)
|
|
||||||
{
|
|
||||||
leaveText.Text = $"OnRequestLeave: {channel.Name}";
|
|
||||||
leaveText.FadeOutFromOne(1000, Easing.InQuint);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Channel createPublicChannel(string name) =>
|
|
||||||
new Channel { Name = name, Type = ChannelType.Public, Id = 1234 };
|
|
||||||
|
|
||||||
private static Channel createPrivateChannel(string username, int id)
|
|
||||||
=> new Channel(new APIUser { Id = id, Username = username });
|
|
||||||
}
|
|
||||||
}
|
|
135
osu.Game/Overlays/Chat/ChannelList/ChannelList.cs
Normal file
135
osu.Game/Overlays/Chat/ChannelList/ChannelList.cs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Online.Chat;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Chat.ChannelList
|
||||||
|
{
|
||||||
|
public class ChannelList : Container
|
||||||
|
{
|
||||||
|
public Action<Channel>? OnRequestSelect;
|
||||||
|
public Action<Channel>? OnRequestLeave;
|
||||||
|
|
||||||
|
public readonly BindableBool SelectorActive = new BindableBool();
|
||||||
|
|
||||||
|
private readonly Dictionary<Channel, ChannelListItem> channelMap = new Dictionary<Channel, ChannelListItem>();
|
||||||
|
|
||||||
|
private ChannelListItemFlow publicChannelFlow = null!;
|
||||||
|
private ChannelListItemFlow privateChannelFlow = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colourProvider.Background6,
|
||||||
|
},
|
||||||
|
new OsuScrollContainer
|
||||||
|
{
|
||||||
|
Padding = new MarginPadding { Vertical = 7 },
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
ScrollbarAnchor = Anchor.TopRight,
|
||||||
|
ScrollDistance = 35f,
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
publicChannelFlow = new ChannelListItemFlow("CHANNELS"),
|
||||||
|
new ChannelListSelector
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding { Bottom = 10 },
|
||||||
|
SelectorActive = { BindTarget = SelectorActive },
|
||||||
|
},
|
||||||
|
privateChannelFlow = new ChannelListItemFlow("DIRECT MESSAGES"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddChannel(Channel channel)
|
||||||
|
{
|
||||||
|
if (channelMap.ContainsKey(channel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChannelListItem item = new ChannelListItem(channel);
|
||||||
|
item.OnRequestSelect += chan => OnRequestSelect?.Invoke(chan);
|
||||||
|
item.OnRequestLeave += chan => OnRequestLeave?.Invoke(chan);
|
||||||
|
item.SelectorActive.BindTarget = SelectorActive;
|
||||||
|
|
||||||
|
ChannelListItemFlow flow = getFlowForChannel(channel);
|
||||||
|
channelMap.Add(channel, item);
|
||||||
|
flow.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveChannel(Channel channel)
|
||||||
|
{
|
||||||
|
if (!channelMap.ContainsKey(channel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChannelListItem item = channelMap[channel];
|
||||||
|
ChannelListItemFlow flow = getFlowForChannel(channel);
|
||||||
|
|
||||||
|
channelMap.Remove(channel);
|
||||||
|
flow.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChannelListItem GetItem(Channel channel)
|
||||||
|
{
|
||||||
|
if (!channelMap.ContainsKey(channel))
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
||||||
|
return channelMap[channel];
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChannelListItemFlow getFlowForChannel(Channel channel)
|
||||||
|
{
|
||||||
|
switch (channel.Type)
|
||||||
|
{
|
||||||
|
case ChannelType.Public:
|
||||||
|
return publicChannelFlow;
|
||||||
|
|
||||||
|
case ChannelType.PM:
|
||||||
|
return privateChannelFlow;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChannelListItemFlow : FillFlowContainer
|
||||||
|
{
|
||||||
|
public ChannelListItemFlow(string label)
|
||||||
|
{
|
||||||
|
Direction = FillDirection.Vertical;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
|
||||||
|
Add(new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = label,
|
||||||
|
Margin = new MarginPadding { Left = 18, Bottom = 5 },
|
||||||
|
Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,12 +29,14 @@ namespace osu.Game.Overlays.Chat.ChannelList
|
|||||||
|
|
||||||
public readonly BindableBool Unread = new BindableBool();
|
public readonly BindableBool Unread = new BindableBool();
|
||||||
|
|
||||||
|
public readonly BindableBool SelectorActive = new BindableBool();
|
||||||
|
|
||||||
private readonly Channel channel;
|
private readonly Channel channel;
|
||||||
|
|
||||||
private Box? hoverBox;
|
private Box hoverBox = null!;
|
||||||
private Box? selectBox;
|
private Box selectBox = null!;
|
||||||
private OsuSpriteText? text;
|
private OsuSpriteText text = null!;
|
||||||
private ChannelListItemCloseButton? close;
|
private ChannelListItemCloseButton close = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Bindable<Channel> selectedChannel { get; set; } = null!;
|
private Bindable<Channel> selectedChannel { get; set; } = null!;
|
||||||
@ -124,31 +126,26 @@ namespace osu.Game.Overlays.Chat.ChannelList
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
selectedChannel.BindValueChanged(change =>
|
selectedChannel.BindValueChanged(_ => updateSelectState(), true);
|
||||||
{
|
SelectorActive.BindValueChanged(_ => updateSelectState(), true);
|
||||||
if (change.NewValue == channel)
|
|
||||||
selectBox?.FadeIn(300, Easing.OutQuint);
|
|
||||||
else
|
|
||||||
selectBox?.FadeOut(200, Easing.OutQuint);
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
Unread.BindValueChanged(change =>
|
Unread.BindValueChanged(change =>
|
||||||
{
|
{
|
||||||
text!.FadeColour(change.NewValue ? colourProvider.Content1 : colourProvider.Light3, 300, Easing.OutQuint);
|
text.FadeColour(change.NewValue ? colourProvider.Content1 : colourProvider.Light3, 300, Easing.OutQuint);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
hoverBox?.FadeIn(300, Easing.OutQuint);
|
hoverBox.FadeIn(300, Easing.OutQuint);
|
||||||
close?.FadeIn(300, Easing.OutQuint);
|
close.FadeIn(300, Easing.OutQuint);
|
||||||
return base.OnHover(e);
|
return base.OnHover(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
hoverBox?.FadeOut(200, Easing.OutQuint);
|
hoverBox.FadeOut(200, Easing.OutQuint);
|
||||||
close?.FadeOut(200, Easing.OutQuint);
|
close.FadeOut(200, Easing.OutQuint);
|
||||||
base.OnHoverLost(e);
|
base.OnHoverLost(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,5 +164,13 @@ namespace osu.Game.Overlays.Chat.ChannelList
|
|||||||
Masking = true,
|
Masking = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSelectState()
|
||||||
|
{
|
||||||
|
if (selectedChannel.Value == channel && !SelectorActive.Value)
|
||||||
|
selectBox.FadeIn(300, Easing.OutQuint);
|
||||||
|
else
|
||||||
|
selectBox.FadeOut(200, Easing.OutQuint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
91
osu.Game/Overlays/Chat/ChannelList/ChannelListSelector.cs
Normal file
91
osu.Game/Overlays/Chat/ChannelList/ChannelListSelector.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
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.Input.Events;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Chat.ChannelList
|
||||||
|
{
|
||||||
|
public class ChannelListSelector : OsuClickableContainer
|
||||||
|
{
|
||||||
|
public readonly BindableBool SelectorActive = new BindableBool();
|
||||||
|
|
||||||
|
private Box hoverBox = null!;
|
||||||
|
private Box selectBox = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
Height = 30;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
hoverBox = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colourProvider.Background3,
|
||||||
|
Alpha = 0f,
|
||||||
|
},
|
||||||
|
selectBox = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = colourProvider.Background4,
|
||||||
|
Alpha = 0f,
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = 18, Right = 10 },
|
||||||
|
Child = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Text = "Add More Channels",
|
||||||
|
Font = OsuFont.Torus.With(size: 17, weight: FontWeight.SemiBold),
|
||||||
|
Colour = colourProvider.Light3,
|
||||||
|
Margin = new MarginPadding { Bottom = 2 },
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Truncate = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
SelectorActive.BindValueChanged(selector =>
|
||||||
|
{
|
||||||
|
if (selector.NewValue)
|
||||||
|
selectBox.FadeIn(300, Easing.OutQuint);
|
||||||
|
else
|
||||||
|
selectBox.FadeOut(200, Easing.OutQuint);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
Action = () => SelectorActive.Value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
hoverBox.FadeIn(300, Easing.OutQuint);
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
hoverBox.FadeOut(200, Easing.OutQuint);
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ using osu.Game.Database;
|
|||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Spectator;
|
using osu.Game.Online.Spectator;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
@ -146,8 +146,10 @@ namespace osu.Game.Skinning.Editor
|
|||||||
{
|
{
|
||||||
anchorLine = new Box
|
anchorLine = new Box
|
||||||
{
|
{
|
||||||
Colour = Color4.Yellow,
|
|
||||||
Height = 2,
|
Height = 2,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Colour = Color4.Yellow,
|
||||||
|
EdgeSmoothness = Vector2.One
|
||||||
},
|
},
|
||||||
originBox = new Box
|
originBox = new Box
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user