Back from a mod card returns to the mods grid; collections link in its own row, status and version no longer cut off; mod cover

This commit is contained in:
cthangover committed 2026-10-22 17:54:07 +02:00
1 parent ec86fc1ce6
commit 9c8be05cc8
10 files changed
+58 -39

No files matched your search

+1 -1
View File
@@ -6,7 +6,6 @@ mod_mod_manager_desc = Nexus-style mod manager: catalog browsing, category filte
mod_manager/menu_title = Mods & Collections mod_manager/menu_title = Mods & Collections
mod_manager/title = Mod Manager mod_manager/title = Mod Manager
mod_manager/back = Close mod_manager/back = Close
mod_manager/back_to_list = Back
mod_manager/search_placeholder = Search mods... mod_manager/search_placeholder = Search mods...
mod_manager/sort_name = By name mod_manager/sort_name = By name
mod_manager/sort_author = By author mod_manager/sort_author = By author
@@ -169,6 +168,7 @@ mod_manager/hub_tab_mods = Mods
mod_manager/hub_tab_collections = Collections mod_manager/hub_tab_collections = Collections
mod_manager/hub_back_to_menu = ← Menu mod_manager/hub_back_to_menu = ← Menu
mod_manager/hub_back_to_gallery = ← Games mod_manager/hub_back_to_gallery = ← Games
mod_manager/hub_back_to_mods = ← Mods
mod_manager/hub_in_one_collection = in {0} collection mod_manager/hub_in_one_collection = in {0} collection
mod_manager/hub_in_many_collections = in {0} collections mod_manager/hub_in_many_collections = in {0} collections
+1 -1
View File
@@ -6,7 +6,6 @@ mod_mod_manager_desc = Менеджер модов в стиле Nexus: ката
mod_manager/menu_title = Моды и коллекции mod_manager/menu_title = Моды и коллекции
mod_manager/title = Менеджер модов mod_manager/title = Менеджер модов
mod_manager/back = Закрыть mod_manager/back = Закрыть
mod_manager/back_to_list = Назад
mod_manager/search_placeholder = Поиск модов... mod_manager/search_placeholder = Поиск модов...
mod_manager/sort_name = По имени mod_manager/sort_name = По имени
mod_manager/sort_author = По автору mod_manager/sort_author = По автору
@@ -169,6 +168,7 @@ mod_manager/hub_tab_mods = Моды
mod_manager/hub_tab_collections = Коллекции mod_manager/hub_tab_collections = Коллекции
mod_manager/hub_back_to_menu = ← Меню mod_manager/hub_back_to_menu = ← Меню
mod_manager/hub_back_to_gallery = ← К играм mod_manager/hub_back_to_gallery = ← К играм
mod_manager/hub_back_to_mods = ← К модам
mod_manager/hub_in_one_collection = в {0} коллекции mod_manager/hub_in_one_collection = в {0} коллекции
mod_manager/hub_in_many_collections = в {0} коллекциях mod_manager/hub_in_many_collections = в {0} коллекциях
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

+8 -1
View File
@@ -75,6 +75,11 @@ clip_text = true
text_overrun_behavior = 3 text_overrun_behavior = 3
theme_override_font_sizes/font_size = 11 theme_override_font_sizes/font_size = 11
[node name="LinkRow" type="HBoxContainer" parent="VBox/Body/Box"]
custom_minimum_size = Vector2(0, 16)
layout_mode = 2
mouse_filter = 2
[node name="MetaRow" type="HBoxContainer" parent="VBox/Body/Box"] [node name="MetaRow" type="HBoxContainer" parent="VBox/Body/Box"]
custom_minimum_size = Vector2(0, 28) custom_minimum_size = Vector2(0, 28)
layout_mode = 2 layout_mode = 2
@@ -84,7 +89,7 @@ theme_override_constants/separation = 6
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 4 size_flags_vertical = 4
mouse_filter = 2 mouse_filter = 1
clip_text = true clip_text = true
text_overrun_behavior = 3 text_overrun_behavior = 3
theme_override_font_sizes/font_size = 11 theme_override_font_sizes/font_size = 11
@@ -105,6 +110,8 @@ anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
clip_text = true
text_overrun_behavior = 3
theme_override_font_sizes/font_size = 11 theme_override_font_sizes/font_size = 11
[node name="ActionRow" type="HBoxContainer" parent="VBox/Body/Box"] [node name="ActionRow" type="HBoxContainer" parent="VBox/Body/Box"]
-4
View File
@@ -63,10 +63,6 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
theme_override_constants/separation = 6 theme_override_constants/separation = 6
[node name="Back" type="Button" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"]
layout_mode = 2
size_flags_horizontal = 0
[node name="Title" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"] [node name="Title" type="Label" parent="Scroll/Content/Hero/HeroMargin/HeroRow/Info"]
layout_mode = 2 layout_mode = 2
autowrap_mode = 3 autowrap_mode = 3
+16 -4
View File
@@ -25,8 +25,9 @@ namespace Mods.ModManager
/// The hub also carries the mockup's cross links: a collection link on a /// The hub also carries the mockup's cross links: a collection link on a
/// mod card switches to the collections tab, a "not found" problem in the /// mod card switches to the collections tab, a "not found" problem in the
/// editor jumps back to the mods tab with the id filled into the search /// editor jumps back to the mods tab with the id filled into the search
/// box (<see cref="ModManagerScreen.SetSearch"/>), and Escape walks back /// box (<see cref="ModManagerScreen.SetSearch"/>). The back button and Escape
/// editor → gallery → mods tab. /// walk back one level at a time — editor → gallery, an open mod card → the
/// mods grid — and only then leave to the menu.
/// </summary> /// </summary>
public partial class ModHubScreen : ModWidget public partial class ModHubScreen : ModWidget
{ {
@@ -223,7 +224,7 @@ namespace Mods.ModManager
return; return;
} }
_back.Text = TranslationServer.Translate("mod_manager/hub_back_to_menu"); _back.Text = TranslationServer.Translate(ModOpen ? "mod_manager/hub_back_to_mods" : "mod_manager/hub_back_to_menu");
_back.TooltipText = _back.Text; _back.TooltipText = _back.Text;
_title.Text = TranslationServer.Translate("mod_manager/menu_title"); _title.Text = TranslationServer.Translate("mod_manager/menu_title");
_segment.Visible = true; _segment.Visible = true;
@@ -235,10 +236,13 @@ namespace Mods.ModManager
_galleryRefresh.Visible = collections; _galleryRefresh.Visible = collections;
} }
/// <summary>Back walks one level up: scheme editor → games gallery, mod card → mods, then the menu.</summary>
private void OnBackPressed() private void OnBackPressed()
{ {
if (_editorOpen) if (_editorOpen)
ShowGallery(); ShowGallery();
else if (ModOpen)
_mods.CloseDetail();
else else
QueueFree(); QueueFree();
} }
@@ -262,8 +266,11 @@ namespace Mods.ModManager
_mods.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect); _mods.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect);
_mods.EnsureConstructed(); _mods.EnsureConstructed();
_mods.CollectionsLinkRequested += () => ShowTab(TabCollections); _mods.CollectionsLinkRequested += () => ShowTab(TabCollections);
_mods.DetailToggled += UpdateHeader;
} }
private bool ModOpen => _activeTab == TabMods && _mods != null && _mods.IsDetailOpen;
private void EnsureGallery() private void EnsureGallery()
{ {
if (_gallery != null) if (_gallery != null)
@@ -350,7 +357,7 @@ namespace Mods.ModManager
/* ═══════════════ Escape chain ═══════════════ */ /* ═══════════════ Escape chain ═══════════════ */
/// <summary>Escape walks back one level: editor → gallery → mods tab.</summary> /// <summary>Escape walks back one level: editor → gallery → mods tab, mod card → mods grid.</summary>
public override void _UnhandledInput(InputEvent @event) public override void _UnhandledInput(InputEvent @event)
{ {
if (!@event.IsActionPressed("ui_cancel")) if (!@event.IsActionPressed("ui_cancel"))
@@ -361,6 +368,11 @@ namespace Mods.ModManager
ShowGallery(); ShowGallery();
GetViewport().SetInputAsHandled(); GetViewport().SetInputAsHandled();
} }
else if (ModOpen)
{
_mods.CloseDetail();
GetViewport().SetInputAsHandled();
}
else if (_activeTab == TabCollections) else if (_activeTab == TabCollections)
{ {
ShowTab(TabMods); ShowTab(TabMods);
+17 -10
View File
@@ -52,6 +52,12 @@ namespace Mods.ModManager
/// </summary> /// </summary>
public bool Embedded { get; set; } public bool Embedded { get; set; }
/// <summary>Whether a mod card is open over the grid.</summary>
public bool IsDetailOpen => _detail != null && _detail.Visible;
/// <summary>Raised when a mod card opens or closes (the hub relabels its back button).</summary>
public event Action DetailToggled;
/// <summary>Raised when a tile or the detail page asks to jump to the collections tab.</summary> /// <summary>Raised when a tile or the detail page asks to jump to the collections tab.</summary>
public event Action CollectionsLinkRequested; public event Action CollectionsLinkRequested;
@@ -153,7 +159,6 @@ namespace Mods.ModManager
_grid.EnabledToggled += OnEnabledToggled; _grid.EnabledToggled += OnEnabledToggled;
_grid.VersionChanged += OnVersionChanged; _grid.VersionChanged += OnVersionChanged;
_grid.CollectionsLinkRequested += OnCollectionsLinkRequested; _grid.CollectionsLinkRequested += OnCollectionsLinkRequested;
_detail.BackRequested += OnDetailBackRequested;
_detail.ActionPressed += OnActionPressed; _detail.ActionPressed += OnActionPressed;
_detail.DeleteRequested += OnDeleteRequested; _detail.DeleteRequested += OnDeleteRequested;
_detail.EnabledToggled += OnEnabledToggled; _detail.EnabledToggled += OnEnabledToggled;
@@ -172,7 +177,6 @@ namespace Mods.ModManager
_grid.EnabledToggled -= OnEnabledToggled; _grid.EnabledToggled -= OnEnabledToggled;
_grid.VersionChanged -= OnVersionChanged; _grid.VersionChanged -= OnVersionChanged;
_grid.CollectionsLinkRequested -= OnCollectionsLinkRequested; _grid.CollectionsLinkRequested -= OnCollectionsLinkRequested;
_detail.BackRequested -= OnDetailBackRequested;
_detail.ActionPressed -= OnActionPressed; _detail.ActionPressed -= OnActionPressed;
_detail.DeleteRequested -= OnDeleteRequested; _detail.DeleteRequested -= OnDeleteRequested;
_detail.EnabledToggled -= OnEnabledToggled; _detail.EnabledToggled -= OnEnabledToggled;
@@ -315,10 +319,17 @@ namespace Mods.ModManager
QueueFree(); QueueFree();
} }
private void OnDetailBackRequested() /// <summary>
/// Closes an open mod card and shows the grid again. The hub's back button and
/// Escape call it first, so "back" from a mod returns to the mods, not to the menu.
/// </summary>
public void CloseDetail()
{ {
if (!_detail.Visible)
return;
_detail.Visible = false; _detail.Visible = false;
_grid.Visible = true; _grid.Visible = true;
DetailToggled?.Invoke();
} }
private void OnCardClicked(ModCardData data) private void OnCardClicked(ModCardData data)
@@ -326,6 +337,7 @@ namespace Mods.ModManager
_detail.Open(data); _detail.Open(data);
_detail.Visible = true; _detail.Visible = true;
_grid.Visible = false; _grid.Visible = false;
DetailToggled?.Invoke();
} }
private void OnSearchChanged(string text) private void OnSearchChanged(string text)
@@ -388,7 +400,7 @@ namespace Mods.ModManager
if (updated != null) if (updated != null)
_detail.Open(updated); _detail.Open(updated);
else else
OnDetailBackRequested(); CloseDetail();
} }
} }
@@ -486,12 +498,7 @@ namespace Mods.ModManager
_restartRequired = true; _restartRequired = true;
_statusMessage = null; _statusMessage = null;
if (_detail.Visible) CloseDetail();
{
_detail.Visible = false;
_grid.Visible = true;
}
RefreshAll(); RefreshAll();
} }
+15 -9
View File
@@ -29,7 +29,7 @@ namespace Mods.ModManager
private OptionButton _versions; private OptionButton _versions;
private Button _action; private Button _action;
private CheckButton _enabled; private CheckButton _enabled;
private HBoxContainer _metaRow; private HBoxContainer _linkRow;
private Button _collectionsLink; private Button _collectionsLink;
private bool _updatingEnabled; private bool _updatingEnabled;
private bool _initialized; private bool _initialized;
@@ -68,7 +68,7 @@ namespace Mods.ModManager
_versions = GetNode<OptionButton>("VBox/Body/Box/MetaRow/VersionHost/Versions"); _versions = GetNode<OptionButton>("VBox/Body/Box/MetaRow/VersionHost/Versions");
_action = GetNode<Button>("VBox/Body/Box/ActionRow/ActionHost/Action"); _action = GetNode<Button>("VBox/Body/Box/ActionRow/ActionHost/Action");
_enabled = GetNode<CheckButton>("VBox/Body/Box/ActionRow/EnabledHost/Enabled"); _enabled = GetNode<CheckButton>("VBox/Body/Box/ActionRow/EnabledHost/Enabled");
_metaRow = GetNode<HBoxContainer>("VBox/Body/Box/MetaRow"); _linkRow = GetNode<HBoxContainer>("VBox/Body/Box/LinkRow");
_author.AddThemeColorOverride("font_color", UiTokens.Muted); _author.AddThemeColorOverride("font_color", UiTokens.Muted);
_source.AddThemeColorOverride("font_color", UiTokens.Muted); _source.AddThemeColorOverride("font_color", UiTokens.Muted);
@@ -106,7 +106,8 @@ namespace Mods.ModManager
{ {
_status.Text = ModStatusNames.Translate(_data.Status); _status.Text = ModStatusNames.Translate(_data.Status);
_status.AddThemeColorOverride("font_color", ModStatusNames.Color(_data.Status)); _status.AddThemeColorOverride("font_color", ModStatusNames.Color(_data.Status));
_status.TooltipText = string.Empty; // A long status next to the version combo may end in an ellipsis.
_status.TooltipText = _status.Text;
} }
UpdateActionButton(); UpdateActionButton();
@@ -160,13 +161,18 @@ namespace Mods.ModManager
} }
_versions.Selected = selectedIndex; _versions.Selected = selectedIndex;
// "v1.2.0 · latest · installed" does not fit the narrow combo: it ends in an
// ellipsis (clip_text in the scene), the full label is in the tooltip.
_versions.TooltipText = _versions.GetItemText(selectedIndex);
} }
/// <summary> /// <summary>
/// Builds the flat "in N collections" cross-link shown between the /// Builds the flat "in N collections" cross-link in its own row above the
/// status label and the version combo. The link is part of the hub /// status. The link is part of the hub mockup: pressing it jumps to the
/// mockup: pressing it jumps to the collections tab. Hidden entirely /// collections tab. It used to share the status row, where its text took the
/// for mods that no playable game references. /// width the status needed ("Installed" was cut off); the row is reserved on
/// every card, empty for mods no playable game references, so all tiles keep
/// one size.
/// </summary> /// </summary>
private void BuildCollectionsLink() private void BuildCollectionsLink()
{ {
@@ -183,8 +189,7 @@ namespace Mods.ModManager
foreach (var state in new[] { "normal", "hover", "pressed", "disabled", "focus" }) foreach (var state in new[] { "normal", "hover", "pressed", "disabled", "focus" })
_collectionsLink.AddThemeStyleboxOverride(state, new StyleBoxEmpty()); _collectionsLink.AddThemeStyleboxOverride(state, new StyleBoxEmpty());
_collectionsLink.Pressed += () => CollectionsLinkRequested?.Invoke(); _collectionsLink.Pressed += () => CollectionsLinkRequested?.Invoke();
_metaRow.AddChild(_collectionsLink); _linkRow.AddChild(_collectionsLink);
_metaRow.MoveChild(_collectionsLink, 1);
} }
private void UpdateCollectionsLink() private void UpdateCollectionsLink()
@@ -282,6 +287,7 @@ namespace Mods.ModManager
return; return;
_data.SelectedDownload = _data.Downloads[(int)index]; _data.SelectedDownload = _data.Downloads[(int)index];
_versions.TooltipText = _versions.GetItemText((int)index);
_data.RecomputeStatus(); _data.RecomputeStatus();
RefreshState(); RefreshState();
VersionChanged?.Invoke(_data); VersionChanged?.Invoke(_data);
-9
View File
@@ -21,7 +21,6 @@ namespace Mods.ModManager
private bool _nodesReady; private bool _nodesReady;
private TextureRect _coverImage; private TextureRect _coverImage;
private Button _back;
private Label _title; private Label _title;
private Label _author; private Label _author;
private Label _meta; private Label _meta;
@@ -40,9 +39,6 @@ namespace Mods.ModManager
private VBoxContainer _conflictsBox; private VBoxContainer _conflictsBox;
private Label _conflictsText; private Label _conflictsText;
/// <summary>Raised by the back button.</summary>
public event Action BackRequested;
/// <summary>Raised when the primary contextual action is pressed.</summary> /// <summary>Raised when the primary contextual action is pressed.</summary>
public event Action<ModCardData> ActionPressed; public event Action<ModCardData> ActionPressed;
@@ -72,7 +68,6 @@ namespace Mods.ModManager
_nodesReady = true; _nodesReady = true;
_coverImage = GetNode<TextureRect>("Scroll/Content/Hero/HeroMargin/HeroRow/Cover/Image"); _coverImage = GetNode<TextureRect>("Scroll/Content/Hero/HeroMargin/HeroRow/Cover/Image");
_back = GetNode<Button>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Back");
_title = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Title"); _title = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Title");
_author = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Author"); _author = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Author");
_meta = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Meta"); _meta = GetNode<Label>("Scroll/Content/Hero/HeroMargin/HeroRow/Info/Meta");
@@ -91,8 +86,6 @@ namespace Mods.ModManager
_conflictsBox = GetNode<VBoxContainer>("Scroll/Content/ConflictsBox"); _conflictsBox = GetNode<VBoxContainer>("Scroll/Content/ConflictsBox");
_conflictsText = GetNode<Label>("Scroll/Content/ConflictsBox/Text"); _conflictsText = GetNode<Label>("Scroll/Content/ConflictsBox/Text");
_back.Text = TranslationServer.Translate("mod_manager/back_to_list");
_back.Pressed += OnBackPressed;
_versions.ItemSelected += OnVersionSelected; _versions.ItemSelected += OnVersionSelected;
_author.AddThemeColorOverride("font_color", UiTokens.Muted); _author.AddThemeColorOverride("font_color", UiTokens.Muted);
@@ -298,8 +291,6 @@ namespace Mods.ModManager
_coverImage.Texture = texture; _coverImage.Texture = texture;
} }
private void OnBackPressed() => BackRequested?.Invoke();
private void OnPrimaryPressed() => ActionPressed?.Invoke(_data); private void OnPrimaryPressed() => ActionPressed?.Invoke(_data);
private void OnDeletePressed() => DeleteRequested?.Invoke(_data); private void OnDeletePressed() => DeleteRequested?.Invoke(_data);