Skip to content

fix: 按控制器和资源过滤预设 - #263

Merged
SweetSmellFox merged 3 commits into
MaaXYZ:masterfrom
Craun718:feat/preset-controller-filter
Oct 24, 2026
Merged

SweetSmellFox merged 3 commits into
MaaXYZ:masterfrom
Craun718:feat/preset-controller-filter

Conversation

@Craun718

@Craun718 Craun718 commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

概述

  • 为 MaaInterfacePreset 新增 controller 和 resource 字段,以兼容 Project Interface 配置
  • 任务页预设列表和新增实例的预设菜单现在会按当前控制器和资源进行过滤
  • 控制器或资源选择发生变化时自动刷新预设列表

关联 Issue

Fixes #262

测试

  • git diff --check
  • 本地构建通过

Sourcery 总结

按当前控制器和资源限制接口预设的可用范围,并在相关配置变化时及时更新预设列表。

新功能:

  • 为接口预设增加可选的控制器和资源适用范围配置。

错误修复:

  • 按当前控制器和资源过滤任务页及新增实例中的可用预设,避免显示不适用的配置。

改进:

  • 在控制器、资源或实例切换时自动刷新预设列表,并完善预设语言变更订阅的生命周期管理。
Original summary in English

Summary by Sourcery

按当前控制器和资源限制接口预设的可用范围,并在相关配置变化时及时更新预设列表。

New Features:

  • 为接口预设增加可选的控制器和资源适用范围配置。

Bug Fixes:

  • 按当前控制器和资源过滤任务页及新增实例中的可用预设,避免显示不适用的配置。

Enhancements:

  • 在控制器、资源或实例切换时自动刷新预设列表,并完善预设语言变更订阅的生命周期管理。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嘿——我发现了 7 个问题

给 AI 代理的提示
请处理这次代码审查中的评论:

## 单独评论

### 评论 1
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="168-170" />
<code_context>
         }
     }

+    private static bool IsPresetApplicableToCurrentInstance(MaaInterface.MaaInterfacePreset preset)
+    {
+        var viewModel = ActiveTab?.TaskQueueViewModel;
+        return viewModel == null
+            || preset.IsApplicableTo(viewModel.GetCurrentControllerName(), viewModel.CurrentResource);
</code_context>
<issue_to_address>
**应用无法构建**

编译项目中的此更改时,`IsPresetApplicableToCurrentInstance` 是静态方法,却读取了实例属性 `ActiveTab`,因此编译器会报告 CS0120,应用也无法构建。

请将此辅助方法改为实例方法,或将活动标签页传入该方法。
</issue_to_address>

### 评论 2
<location path="MFAAvalonia/ViewModels/Other/InstanceTabViewModel.cs" line_range="85" />
<code_context>
+        if (e.PropertyName is nameof(TaskQueueViewModel.CurrentController)
+            or nameof(TaskQueueViewModel.CurrentResource))
+        {
+            if (ActiveTab == this)
+            {
+                DispatcherHelper.RunOnMainThread(() =>
</code_context>
<issue_to_address>
**预设筛选无法编译**

`InstanceTabViewModel` 没有 `ActiveTab` 成员,而且静态方法 `IsPresetApplicableToCurrentInstance` 无法访问实例属性 `ActiveTab`。这些引用会导致编译错误,因此应用无法构建。

在实例处理程序中通过标签栏视图模型引用活动标签页,并将适用性辅助方法改为实例方法,或显式将活动标签页传入该方法。

另请参见 `MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs:170`。
</issue_to_address>

### 评论 3
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="170" />
<code_context>

+    private static bool IsPresetApplicableToCurrentInstance(MaaInterface.MaaInterfacePreset preset)
+    {
+        var viewModel = ActiveTab?.TaskQueueViewModel;
+        return viewModel == null
+            || preset.IsApplicableTo(viewModel.GetCurrentControllerName(), viewModel.CurrentResource);
</code_context>
<issue_to_address>
**新实例会获得不匹配的预设**

当活动标签页不是最右侧标签页,且两者选择的控制器或资源不同时,`IsPresetApplicableToCurrentInstance` 会依据 `ActiveTab` 进行筛选,但 `AddInstanceCoreAsync` 会从 `Tabs.LastOrDefault()` 复制配置。因此,菜单可能会显示不适用于新实例的预设,同时隐藏适用的预设。

请根据 `AddInstanceCoreAsync` 复制到新实例中的控制器和资源配置来筛选预设。
</issue_to_address>

### 评论 4
<location path="MFAAvalonia/Extensions/MaaFW/MaaInterface.cs" line_range="1285-1292" />
<code_context>
         public string? Icon { get; set; }

+        /// <summary>支持的控制器名称列表;为空表示支持所有控制器</summary>
+        [JsonProperty("controller")]
+        [JsonConverter(typeof(GenericSingleOrListConverter<string>))]
+        public List<string>? Controller { get; set; }
+
+        /// <summary>支持的资源包名称列表;为空表示支持所有资源包</summary>
+        [JsonProperty("resource")]
+        [JsonConverter(typeof(GenericSingleOrListConverter<string>))]
+        public List<string>? Resource { get; set; }
+
         /// <summary>预设包含的任务配置列表</summary>
</code_context>
<issue_to_address>
**启动时会应用不兼容的预设**

如果初始设置中没有实例配置,而预设声明了控制器或资源限制,`MaaProcessorManager` 会为每个预设创建并应用一个实例,却不检查该实例是否满足相应的控制器或资源约束。因此,首次设置时仍会将预设应用到不支持它们的实例。

在自动创建或应用由预设生成的实例之前,请根据实例的控制器和资源筛选预设。
</issue_to_address>

### 评论 5
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="512" />
<code_context>
     {
         var presets = MaaProcessor.Interface?.Preset;
-        HasInstancePresets = presets is { Count: > 0 };
+        HasInstancePresets = presets?.Any(IsPresetApplicableToCurrentInstance) == true;
         InstancePresets = presets;
         RefreshFilteredInstancePresets();
</code_context>
<issue_to_address>
**预设菜单使用了过期的标签页结果**

预设列表刷新后,如果活动标签页发生变化,`ActiveTab` 变更时不会运行 `RefreshInstancePresets`,因此 `HasInstancePresets` 和 `FilteredInstancePresets` 仍保留上一个标签页的适用性结果。`AddInstance` 可能会隐藏适用的预设,或显示不适用的预设。

每当 `ActiveTab` 发生变化时,请同时刷新预设可见性标志和筛选后的列表。
</issue_to_address>

### 评论 6
<location path="MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs" line_range="457" />
<code_context>
                     _pendingResourceSelection = null;
                 }

+                RefreshPresets();
                 if (!string.Equals(CurrentResource, resolvedResource, StringComparison.Ordinal))
                 {
</code_context>
<issue_to_address>
**任务页面显示过期的预设**

用户在不更改控制器的情况下更改资源时,`CurrentResource` 会更新所选资源及其任务,却不会调用 `RefreshPresets`,导致 `TaskQueueViewModel.Presets` 仍按先前的资源进行筛选,任务页面因而显示错误的预设。

每当 `CurrentResource` 发生变化时,请刷新预设。

另请参见 `MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:857`、`MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:860-863`。
</issue_to_address>

### 评论 7
<location path="MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs" line_range="457" />
<code_context>
                     _pendingResourceSelection = null;
                 }

+                RefreshPresets();
                 if (!string.Equals(CurrentResource, resolvedResource, StringComparison.Ordinal))
                 {
</code_context>
<issue_to_address>
**语言更新会重复执行**

用户在预设释放之前反复更改控制器或资源选择时,`RefreshPresets` 会调用 `InitializeDisplayName`,为每个预设额外添加一个 `LanguageChanged` 处理程序;而 `Dispose` 只会移除一个订阅。处理程序会不断累积、保留已替换的预设,并导致语言更改时重复更新。

请确保每个预设只订阅一次语言更改事件,并在预设被替换或释放时取消订阅。

另请参见 `MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:1670`。
</issue_to_address>

Sourcery 对开源项目免费——如果您喜欢我们的审查,欢迎分享 ✨
Original comment in English

Hey - I've found 7 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="168-170" />
<code_context>
         }
     }

+    private static bool IsPresetApplicableToCurrentInstance(MaaInterface.MaaInterfacePreset preset)
+    {
+        var viewModel = ActiveTab?.TaskQueueViewModel;
+        return viewModel == null
+            || preset.IsApplicableTo(viewModel.GetCurrentControllerName(), viewModel.CurrentResource);
</code_context>
<issue_to_address>
**Application fails to build**

When the project compiles this change, `IsPresetApplicableToCurrentInstance` is static but reads the instance property `ActiveTab`, so the compiler reports CS0120 and the application cannot build.

Make the helper an instance method or pass the active tab into it.
</issue_to_address>

### Comment 2
<location path="MFAAvalonia/ViewModels/Other/InstanceTabViewModel.cs" line_range="85" />
<code_context>
+        if (e.PropertyName is nameof(TaskQueueViewModel.CurrentController)
+            or nameof(TaskQueueViewModel.CurrentResource))
+        {
+            if (ActiveTab == this)
+            {
+                DispatcherHelper.RunOnMainThread(() =>
</code_context>
<issue_to_address>
**Preset filtering does not compile**

`InstanceTabViewModel` has no `ActiveTab` member, and the static `IsPresetApplicableToCurrentInstance` method cannot access the instance `ActiveTab` property. These references produce compiler errors, so the application cannot build.

Reference the active tab through the tab-bar view model in the instance handler, and make the applicability helper an instance method or pass it the active tab explicitly.

Also at `MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs:170`.
</issue_to_address>

### Comment 3
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="170" />
<code_context>

+    private static bool IsPresetApplicableToCurrentInstance(MaaInterface.MaaInterfacePreset preset)
+    {
+        var viewModel = ActiveTab?.TaskQueueViewModel;
+        return viewModel == null
+            || preset.IsApplicableTo(viewModel.GetCurrentControllerName(), viewModel.CurrentResource);
</code_context>
<issue_to_address>
**New instances get mismatched presets**

When the active tab is not the rightmost tab and their controller or resource selections differ, `IsPresetApplicableToCurrentInstance` filters against `ActiveTab`, but `AddInstanceCoreAsync` copies configuration from `Tabs.LastOrDefault()`. The menu therefore offers presets that do not fit the new instance and hides presets that do.

Filter presets using the controller and resource configuration that `AddInstanceCoreAsync` copies into the new instance.
</issue_to_address>

### Comment 4
<location path="MFAAvalonia/Extensions/MaaFW/MaaInterface.cs" line_range="1285-1292" />
<code_context>
         public string? Icon { get; set; }

+        /// <summary>支持的控制器名称列表;为空表示支持所有控制器</summary>
+        [JsonProperty("controller")]
+        [JsonConverter(typeof(GenericSingleOrListConverter<string>))]
+        public List<string>? Controller { get; set; }
+
+        /// <summary>支持的资源包名称列表;为空表示支持所有资源包</summary>
+        [JsonProperty("resource")]
+        [JsonConverter(typeof(GenericSingleOrListConverter<string>))]
+        public List<string>? Resource { get; set; }
+
         /// <summary>预设包含的任务配置列表</summary>
</code_context>
<issue_to_address>
**Startup applies incompatible presets**

When initial setup has no instance configurations and presets declare controller or resource restrictions, `MaaProcessorManager` creates and applies an instance for each preset without checking its controller or resource constraints, so first-time setup still applies presets to instances where they are unsupported.

Filter presets by the instance's controller and resource before auto-creating or applying preset-backed instances.
</issue_to_address>

### Comment 5
<location path="MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs" line_range="512" />
<code_context>
     {
         var presets = MaaProcessor.Interface?.Preset;
-        HasInstancePresets = presets is { Count: > 0 };
+        HasInstancePresets = presets?.Any(IsPresetApplicableToCurrentInstance) == true;
         InstancePresets = presets;
         RefreshFilteredInstancePresets();
</code_context>
<issue_to_address>
**Preset menu uses stale tab results**

When the active tab changes after the preset list has been refreshed, `RefreshInstancePresets` does not run when `ActiveTab` changes, so `HasInstancePresets` and `FilteredInstancePresets` retain the previous tab's applicability results. `AddInstance` can hide applicable presets or offer presets that do not apply.

Refresh both the preset visibility flag and filtered list whenever `ActiveTab` changes.
</issue_to_address>

### Comment 6
<location path="MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs" line_range="457" />
<code_context>
                     _pendingResourceSelection = null;
                 }

+                RefreshPresets();
                 if (!string.Equals(CurrentResource, resolvedResource, StringComparison.Ordinal))
                 {
</code_context>
<issue_to_address>
**Task page shows stale presets**

When the user changes the resource without changing the controller, `CurrentResource` updates the selected resource and its tasks without calling `RefreshPresets`, so `TaskQueueViewModel.Presets` remains filtered for the previous resource and the task page shows the wrong presets.

Refresh presets whenever `CurrentResource` changes.

Also at `MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:857`, `MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:860-863`.
</issue_to_address>

### Comment 7
<location path="MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs" line_range="457" />
<code_context>
                     _pendingResourceSelection = null;
                 }

+                RefreshPresets();
                 if (!string.Equals(CurrentResource, resolvedResource, StringComparison.Ordinal))
                 {
</code_context>
<issue_to_address>
**Language updates run repeatedly**

When the user changes controller or resource selections repeatedly before presets are disposed, `RefreshPresets` calls `InitializeDisplayName`, which adds another `LanguageChanged` handler for each preset; `Dispose` removes only one subscription. Handlers accumulate, retain replaced presets, and cause repeated updates on language changes.

Ensure each preset has only one language-change subscription and unsubscribe it when the preset is replaced or disposed.

Also at `MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs:1670`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs Outdated
Comment thread MFAAvalonia/ViewModels/Other/InstanceTabViewModel.cs Outdated
Comment thread MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs Outdated
Comment thread MFAAvalonia/Extensions/MaaFW/MaaInterface.cs
Comment thread MFAAvalonia/ViewModels/Other/InstanceTabBarViewModel.cs Outdated
Comment thread MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs Outdated
Comment thread MFAAvalonia/ViewModels/Pages/TaskQueueViewModel.cs Outdated
@Craun718 Craun718 changed the title fix: filter presets by controller and resource fix: 按控制器和资源过滤预设 Oct 21, 2026
@Craun718
Craun718 marked this pull request as draft October 21, 2026 16:51
@Craun718

Copy link
Copy Markdown
Member Author

Hold on, 原来官方协议还没有吗

@SweetSmellFox
SweetSmellFox merged commit 3f088f8 into MaaXYZ:master Oct 24, 2026
20 checks passed
@Craun718

Copy link
Copy Markdown
Member Author

现在有了(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

请求适配pretask的controller属性

2 participants