Skip to content

Perf Policy Group generate#8855

Merged
2dust merged 9 commits into2dust:masterfrom
DHR60:fix2
Mar 1, 2026
Merged

Perf Policy Group generate#8855
2dust merged 9 commits into2dust:masterfrom
DHR60:fix2

Conversation

@DHR60
Copy link
Copy Markdown
Contributor

@DHR60 DHR60 commented Feb 27, 2026

一键生成策略组

#8848 (comment)

可生成 全部配置项 和 按地区分组 策略组

生成后将自动滚动到生成的策略组位置

@2dust 2dust mentioned this pull request Feb 28, 2026
// Matches subscription-info noise words in both Chinese and English.
// Chinese: 剩余(remaining), 过期/到期(expired/expiry), 重置(reset)
// English: remaining, expir(e/ed/y), reset
private const string PolicyGroupExcludeKeywords = @"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset";
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

PolicyGroupExcludeKeywords PolicyGroupRegionFilters ,是否放到 Global 中合适?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

第一版就是放在 Global 里的,主要是顾虑一个是中文和 emoji 这种,另一个是只有 ConfigHandler 使用

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

不排除后面可能在编辑组的时候,会让用户自己选择 PolicyGroupRegionFilters 下拉

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

那就改成 editable combobox 这种?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

PolicyGroupRegionFilters 也放到 Global 里面吗?

稍微有点不好看

    private const string PolicyGroupExcludeKeywords = @"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset";

    public const string PolicyGroupDefaultAllFilter = $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$";

    private static string CombineWithDefaultAllFilter(string regionPattern)
    {
        return $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*(?:{regionPattern}).*$";
    }

    public static readonly Dictionary<string, string> PolicyGroupRegionFilters = new()
    {
        { "JP", CombineWithDefaultAllFilter("日本|\\\\b[Jj][Pp]\\\\b|🇯🇵|[Jj]apan") },
        { "US", CombineWithDefaultAllFilter("美国|\\b[Uu][Ss]\\b|🇺🇸|[Uu]nited [Ss]tates|\\b[Uu][Ss][Aa]\\b") },
        { "HK", CombineWithDefaultAllFilter("香港|\\b[Hh][Kk]\\b|🇭🇰|[Hh]ong ?[Kk]ong") },
        { "TW", CombineWithDefaultAllFilter("台湾|台灣|\\b[Tt][Ww]\\b|🇹🇼|[Tt]aiwan") },
        { "KR", CombineWithDefaultAllFilter("韩国|\\b[Kk][Rr]\\b|🇰🇷|[Kk]orea") },
        { "SG", CombineWithDefaultAllFilter("新加坡|\\b[Ss][Gg]\\b|🇸🇬|[Ss]ingapore") },
        { "DE", CombineWithDefaultAllFilter("德国|\\b[Dd][Ee]\\b|🇩🇪|[Gg]ermany") },
        { "FR", CombineWithDefaultAllFilter("法国|\\b[Ff][Rr]\\b|🇫🇷|[Ff]rance") },
        { "GB", CombineWithDefaultAllFilter("英国|\\b[Gg][Bb]\\b|🇬🇧|[Uu]nited [Kk]ingdom|[Bb]ritain") },
        { "CA", CombineWithDefaultAllFilter("加拿大|🇨🇦|[Cc]anada") },
        { "AU", CombineWithDefaultAllFilter("澳大利亚|\\b[Aa][Uu]\\b|🇦🇺|[Aa]ustralia") },
        { "RU", CombineWithDefaultAllFilter("俄罗斯|\\b[Rr][Uu]\\b|🇷🇺|[Rr]ussia") },
        { "BR", CombineWithDefaultAllFilter("巴西|\\b[Bb][Rr]\\b|🇧🇷|[Bb]razil") },
        { "IN", CombineWithDefaultAllFilter("印度|🇮🇳|[Ii]ndia") },
        { "VN", CombineWithDefaultAllFilter("越南|\\b[Vv][Nn]\\b|🇻🇳|[Vv]ietnam") },
        { "ID", CombineWithDefaultAllFilter("印度尼西亚|\\b[Ii][Dd]\\b|🇮🇩|[Ii]ndonesia") },
        { "MX", CombineWithDefaultAllFilter("墨西哥|\\b[Mm][Xx]\\b|🇲🇽|[Mm]exico") }
    };

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

对, editable combobox。 你现在要加上吗?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

加上吧,打算是在 Global 里加上

private const string PolicyGroupExcludeKeywords = @"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset";

public const string PolicyGroupDefaultAllFilter = $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$";

再加上个简单的例子组个 List

PolicyGroupRegionFilters 就不放在 Global 里了,Global 里放个函数看起来怪怪的

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

函数不放进去, public const string 放入吧

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Profiles context menu and underlying ViewModel/handler logic to support “one-click” Policy Group generation, including generating a single “all configurations” group and generating multiple groups “by region”, with automatic selection of the newly created group.

Changes:

  • Replaced the old “multi-select generate policy group” menu/actions with two new actions: generate for all configs, and generate by region.
  • Added new ConfigHandler helpers to create filter-based PolicyGroup profiles (default exclude “traffic/expiry” noise words, plus region matching).
  • Updated ProfilesViewModel selection logic to auto-select the newly generated group after refresh.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
v2rayN/v2rayN/Views/ProfilesView.xaml(.cs) Reworked WPF context menu and command bindings to the new “generate group” actions.
v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml(.cs) Same menu/command binding changes for the desktop UI.
v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs Added new commands + pending-selection behavior to focus the generated group.
v2rayN/ServiceLib/Handler/ConfigHandler.cs Implemented AddGroupAllServer / AddGroupRegionServer and new filter/region regex helpers.
v2rayN/ServiceLib/Manager/GroupProfileManager.cs Adjusted sub-child selection logic (but introduces a functional regression—see comments).
v2rayN/ServiceLib/Resx/ResUI*.resx (+ Designer) Removed old menu keys and added new menu localization keys.
Files not reviewed (1)
  • v2rayN/ServiceLib/Resx/ResUI.Designer.cs: Language not supported
Comments suppressed due to low confidence (1)

v2rayN/ServiceLib/Handler/ConfigHandler.cs:1220

  • AddGroupAllServer always creates a PolicyGroup profile even if the computed child list is empty (e.g., subscription contains only excluded “traffic/expiry” noise words, or the filter is too restrictive). This can leave behind empty/invalid groups. Consider resolving child items via GroupProfileManager.GetChildProfileItemsByProtocolExtra(extraItem) first (similar to AddGroupRegionServer) and return Success=false (or skip creation) when there are no matching children.
    public static async Task<RetResult> AddGroupAllServer(Config config, SubItem? subItem)
    {
        var result = new RetResult();

        var indexId = Utils.GetGuid(false);
        var subId = subItem?.Id;

        var remark = subItem is null ? ResUI.TbConfigTypePolicyGroup : $"{subItem.Remarks} - {ResUI.TbConfigTypePolicyGroup}";
        var profile = new ProfileItem
        {
            IndexId = indexId,
            CoreType = ECoreType.Xray,
            ConfigType = EConfigType.PolicyGroup,
            Remarks = remark,
            IsSub = false
        };
        if (!subId.IsNullOrEmpty())
        {
            profile.Subid = subId;
        }
        var extraItem = new ProtocolExtraItem
        {
            MultipleLoad = EMultipleLoad.LeastPing,
            GroupType = profile.ConfigType.ToString(),
            SubChildItems = subId,
            Filter = PolicyGroupDefaultAllFilter,
        };
        profile.SetProtocolExtra(extraItem);
        var ret = await AddServerCommon(config, profile, true);
        result.Success = ret == 0;
        result.Data = indexId;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1663 to +1669
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The newly added menu strings in the zh-Hant resource file are in English (e.g., "Generate Policy Group", "All configurations", "Group by Region"), which is a regression compared to the previously localized menu entries in this file. Please provide Traditional Chinese translations for these new keys (or remove the entries to fall back to the default resource).

Suggested change
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
<value>生成策略群組</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>所有設定</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>按地區分組</value>

Copilot uses AI. Check for mistakes.
Comment on lines +1666 to +1672
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The newly added menu strings in the Russian resource file are in English ("Generate Policy Group", "All configurations", "Group by Region"). Since the removed keys were translated, this is a user-visible localization regression. Please add Russian translations for these new keys (or omit them to fall back to the default resource).

Suggested change
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
<value>Создать группу политик</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>Все конфигурации</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Сгруппировать по региону</value>

Copilot uses AI. Check for mistakes.
Comment on lines +1666 to +1672
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The newly added menu strings in the Hungarian resource file are in English ("Generate Policy Group", "All configurations", "Group by Region"). This is a localization regression compared to the previously translated entries removed in this PR. Please add Hungarian translations for these new keys (or omit them to fall back to the default resource).

Suggested change
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
<value>Házirendcsoport létrehozása</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>Minden konfiguráció</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Csoportosítás régió szerint</value>

Copilot uses AI. Check for mistakes.
Comment on lines +1663 to +1669
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The newly added menu strings in the French resource file are in English ("Generate Policy Group", "All configurations", "Group by Region"), whereas the removed keys were French. Please translate these new keys to French (or omit them to fall back to the default resource) to avoid a UI language regression.

Suggested change
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
<value>Générer un groupe de stratégies</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>Toutes les configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Grouper par région</value>

Copilot uses AI. Check for mistakes.
Comment on lines +1666 to +1672
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The newly added menu strings in the fa-Ir resource file are in English ("Generate Policy Group", "All configurations", "Group by Region"). Since the removed keys had localized values, this is a user-visible regression. Please provide Persian translations for these keys (or omit them to fall back to the default resource).

Suggested change
<value>Generate Policy Group</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>All configurations</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>Group by Region</value>
<value>ایجاد گروه سیاست</value>
</data>
<data name="menuAllServers" xml:space="preserve">
<value>همه پیکربندی‌ها</value>
</data>
<data name="menuGenRegionGroup" xml:space="preserve">
<value>گروه‌بندی بر اساس منطقه</value>

Copilot uses AI. Check for mistakes.
@DHR60
Copy link
Copy Markdown
Contributor Author

DHR60 commented Feb 28, 2026

Done

@2dust 2dust merged commit a3ff310 into 2dust:master Mar 1, 2026
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.

3 participants