private RepoTreeItem FilterByTagPrefix(ILoadedRepository repo, string prefix, Func <string, string> convertor)
        {
            // var nodes = new ObservableCollection<PackageCategoryTreeItem>();

            var map = new Dictionary <string, List <PackageMenuItem> >();

            foreach (var package in repo.Packages.Packages)
            {
                if (package.Value == null)
                {
                    continue;
                }

                IDescriptor descriptor = package.Value !;

                var pkgKey  = PackageKey.Create(repo.Index.Url, descriptor.Id);
                var release = repo.Release(pkgKey);
                var payload = release?.WindowsExecutable();

                if (release == null || payload == null)
                {
                    continue;
                }

                var tags = Iter.ToArray(descriptor.Tags.Where(x => x.StartsWith(prefix)));

                if (tags.IsNullOrEmpty())
                {
                    tags = new[] { prefix };
                }

                foreach (var tag in tags)
                {
                    if (!map.ContainsKey(tag))
                    {
                        map[tag] = new List <PackageMenuItem>();
                    }

                    map[tag].Add(new PackageMenuItem(_store,
                                                     pkgKey, payload, descriptor.NativeName() ?? "<>", release.Version));
                }
            }

            var categoriesSet = new SortedSet <PackageCategoryTreeItem>(map.OrderBy(x => x.Key).Map(x => {
                x.Value.Sort();
                var items = new ObservableCollection <PackageMenuItem>(x.Value);
                return(new PackageCategoryTreeItem(_store, convertor(x.Key), items));
            }));

            var categories = new ObservableCollection <PackageCategoryTreeItem>(categoriesSet);

            return(new RepoTreeItem(repo.Index.NativeName(), categories));
        }