维护代码、本地化;合并时的遗留修改

This commit is contained in:
LA
2026-03-05 21:15:17 +08:00
parent 719e191cbb
commit 514ddbfd96
5 changed files with 14 additions and 279 deletions

View File

@@ -124,7 +124,7 @@ namespace osu.Game.Collections
},
new PopupDialogDangerousButton
{
Text = EzSongSelectStrings.REMOVE_FROM_COLLECTION,
Text = EzSongSelectStrings.REMOVE_INTERSECTION,
Action = onRemoveIntersection,
},
new PopupDialogCancelButton

View File

@@ -43,5 +43,13 @@ namespace osu.Game.LAsEzExtensions.Localization
"按键音预览:\n0 关闭; \n1 蓝灯开启 (全量音效预览); \n2 黄灯开启 (全量音效预览, 游戏中自动播放 note 音效, 按键不再触发样本播放) ",
"Key sound preview: \n0 Off; \n1 BlueLight (keypress triggers samples); "
+ "\n2 GoldLight (preserve preview in song select; in gameplay auto-play note samples, keypresses no longer trigger sample playback)");
public static readonly LocalisableString CLEAR_SELECTION = new EzLocalizationManager.EzLocalisableString(
"点此处可清除过滤选择。\n(CS: cs ±0.5)",
"Click here to clear the filter selection.\n(CS: cs ±0.5)");
public static readonly LocalisableString MULTI_SELECT_BUTTON_TOOLTIP = new EzLocalizationManager.EzLocalisableString(
"多选模式",
"Multi-select mode");
}
}

View File

@@ -1,276 +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 System;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osuTK;
using Realms;
namespace osu.Game.LAsEzExtensions.Screens
{
public partial class EzToCollection : OsuDropdown<CollectionFilterMenuItem>
{
protected virtual bool ShowManageCollectionsItem => true;
public Action? RequestFilter { private get; set; }
private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>();
[Resolved]
private ManageCollectionsDialog? manageCollectionsDialog { get; set; }
[Resolved]
private RealmAccess realm { get; set; } = null!;
private IDisposable? realmSubscription;
private readonly CollectionFilterMenuItem allBeatmapsItem = new AllBeatmapsCollectionFilterMenuItem();
public EzToCollection()
{
ItemSource = filters;
Current.Value = allBeatmapsItem;
AlwaysShowSearchBar = true;
}
protected override void LoadComplete()
{
base.LoadComplete();
realmSubscription = realm.RegisterForNotifications(r => r.All<BeatmapCollection>().OrderBy(c => c.Name), collectionsChanged);
Current.BindValueChanged(selectionChanged);
}
private void collectionsChanged(IRealmCollection<BeatmapCollection> collections, ChangeSet? changes)
{
if (changes == null)
{
filters.Clear();
filters.Add(allBeatmapsItem);
filters.AddRange(collections.Select(c => new CollectionFilterMenuItem(c.ToLive(realm))));
if (ShowManageCollectionsItem)
filters.Add(new ManageCollectionsFilterMenuItem());
}
else
{
foreach (int i in changes.DeletedIndices.OrderDescending())
filters.RemoveAt(i + 1);
foreach (int i in changes.InsertedIndices)
filters.Insert(i + 1, new CollectionFilterMenuItem(collections[i].ToLive(realm)));
var selectedItem = SelectedItem?.Value;
foreach (int i in changes.NewModifiedIndices)
{
var updatedItem = collections[i];
// This is responsible for updating the state of the +/- button and the collection's name.
// TODO: we can probably make the menu items update with changes to avoid this.
filters.RemoveAt(i + 1);
filters.Insert(i + 1, new CollectionFilterMenuItem(updatedItem.ToLive(realm)));
if (updatedItem.ID == selectedItem?.Collection?.ID)
{
// This current update and schedule is required to work around dropdown headers not updating text even when the selected item
// changes. It's not great but honestly the whole dropdown menu structure isn't great. This needs to be fixed, but I'll issue
// a warning that it's going to be a frustrating journey.
Current.Value = allBeatmapsItem;
Schedule(() =>
{
// current may have changed before the scheduled call is run.
if (Current.Value != allBeatmapsItem)
return;
Current.Value = filters.SingleOrDefault(f => f.Collection?.ID == selectedItem.Collection?.ID) ?? filters[0];
});
// Trigger an external re-filter if the current item was in the change set.
RequestFilter?.Invoke();
break;
}
}
}
}
private Live<BeatmapCollection>? lastFiltered;
private void selectionChanged(ValueChangedEvent<CollectionFilterMenuItem> filter)
{
// May be null during .Clear().
if (filter.NewValue.IsNull())
return;
// Never select the manage collection filter - rollback to the previous filter.
// This is done after the above since it is important that bindable is unbound from OldValue, which is lost after forcing it back to the old value.
if (filter.NewValue is ManageCollectionsFilterMenuItem)
{
Current.Value = filter.OldValue;
manageCollectionsDialog?.Show();
return;
}
var newCollection = filter.NewValue.Collection;
// This dropdown be weird.
// We only care about filtering if the actual collection has changed.
if (newCollection != lastFiltered)
{
RequestFilter?.Invoke();
lastFiltered = newCollection;
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
realmSubscription?.Dispose();
}
protected override LocalisableString GenerateItemText(CollectionFilterMenuItem item) => item.CollectionName;
protected sealed override DropdownHeader CreateHeader() => CreateCollectionHeader();
protected sealed override DropdownMenu CreateMenu() => CreateCollectionMenu();
protected virtual CollectionDropdownHeader CreateCollectionHeader() => new CollectionDropdownHeader();
protected virtual CollectionDropdownMenu CreateCollectionMenu() => new CollectionDropdownMenu();
public partial class CollectionDropdownHeader : OsuDropdownHeader
{
public CollectionDropdownHeader()
{
Height = 25;
Chevron.Size = new Vector2(12);
Foreground.Padding = new MarginPadding { Top = 4, Bottom = 4, Left = 8, Right = 8 };
}
}
protected partial class CollectionDropdownMenu : OsuDropdownMenu
{
public CollectionDropdownMenu()
{
MaxHeight = 200;
}
protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new CollectionDropdownDrawableMenuItem(item)
{
BackgroundColourHover = HoverColour,
BackgroundColourSelected = SelectionColour
};
}
protected partial class CollectionDropdownDrawableMenuItem : OsuDropdownMenu.DrawableOsuDropdownMenuItem
{
private IconButton addOrRemoveButton = null!;
private bool beatmapInCollection;
private readonly Live<BeatmapCollection>? collection;
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
public CollectionDropdownDrawableMenuItem(MenuItem item)
: base(item)
{
collection = ((DropdownMenuItem<CollectionFilterMenuItem>)item).Value.Collection;
}
[BackgroundDependencyLoader]
private void load()
{
AddInternal(addOrRemoveButton = new NoFocusChangeIconButton
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
X = -OsuScrollContainer.SCROLL_BAR_WIDTH,
Scale = new Vector2(0.65f),
Action = addOrRemove,
});
}
protected override void LoadComplete()
{
base.LoadComplete();
if (collection != null)
{
beatmap.BindValueChanged(_ =>
{
beatmapInCollection = collection.PerformRead(c => c.BeatmapMD5Hashes.Contains(beatmap.Value.BeatmapInfo.MD5Hash));
addOrRemoveButton.Enabled.Value = !beatmap.IsDefault;
addOrRemoveButton.Icon = beatmapInCollection ? FontAwesome.Solid.MinusSquare : FontAwesome.Solid.PlusSquare;
addOrRemoveButton.TooltipText = beatmapInCollection ? "Remove selected beatmap" : "Add selected beatmap";
updateButtonVisibility();
}, true);
}
updateButtonVisibility();
}
protected override bool OnHover(HoverEvent e)
{
updateButtonVisibility();
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
updateButtonVisibility();
base.OnHoverLost(e);
}
protected override void OnSelectChange()
{
base.OnSelectChange();
updateButtonVisibility();
}
private void updateButtonVisibility()
{
if (collection == null)
addOrRemoveButton.Alpha = 0;
else
addOrRemoveButton.Alpha = IsHovered || IsPreSelected || beatmapInCollection ? 1 : 0;
}
private void addOrRemove()
{
Debug.Assert(collection != null);
collection.PerformWrite(c =>
{
if (!c.BeatmapMD5Hashes.Remove(beatmap.Value.BeatmapInfo.MD5Hash))
c.BeatmapMD5Hashes.Add(beatmap.Value.BeatmapInfo.MD5Hash);
});
}
protected override Drawable CreateContent() => (Content)base.CreateContent();
private partial class NoFocusChangeIconButton : IconButton
{
public override bool ChangeFocusOnClick => false;
}
}
}
}

View File

@@ -15,6 +15,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.LAsEzExtensions.Configuration;
using osu.Game.LAsEzExtensions.Localization;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osuTK;
@@ -84,7 +85,7 @@ namespace osu.Game.LAsEzExtensions.UserInterface
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Shear = new Vector2(0),
TooltipText = "Clear selection",
TooltipText = EzSongSelectStrings.CLEAR_SELECTION,
},
tabControl = new ShearedCsModeTabControl
{
@@ -98,7 +99,7 @@ namespace osu.Game.LAsEzExtensions.UserInterface
Shear = new Vector2(0),
Text = "K +",
Height = 30f,
TooltipText = "Enable multi-select",
TooltipText = EzSongSelectStrings.MULTI_SELECT_BUTTON_TOOLTIP,
}
}
}

View File

@@ -821,6 +821,8 @@ namespace osu.Game.Screens.Select
public int LastFilterPanels { get; private set; }
public int FilterRuns => filterRuns;
public void Filter(FilterCriteria criteria, bool showLoadingImmediately = false)
{
bool resetDisplay = grouping.BeatmapSetsGroupedTogether != BeatmapCarouselFilterGrouping.ShouldGroupBeatmapsTogether(criteria);