public static async IAsyncEnumerable <BookmarkTreeNode> GetAllParentAsync(this IBookmarksApi bookmarksApi,
                                                                              string id)
    {
        var node = await bookmarksApi.Get(id);

        var currentNode   = node?.FirstOrDefault();
        var maxLevelCount = 5;
        var i             = 0;

        while (currentNode != null)
        {
            yield return(currentNode);

            if (++i > maxLevelCount)
            {
                yield break;
            }

            if (!string.IsNullOrEmpty(currentNode.ParentId))
            {
                var nodes = await bookmarksApi.Get(currentNode.ParentId);

                currentNode = nodes?.FirstOrDefault();
            }
        }
    }
    public async ValueTask StartAsync()
    {
        await _bookmarksApi.OnRemoved.AddListener(async (s, info) =>
        {
            var nodes = GetAllChildren(new[] { info.Node });
            foreach (var bookmarkTreeNode in nodes)
            {
                await _bkManager.DeleteAsync(bookmarkTreeNode.Url);
            }

            _logger.LogInformation("Bookmark data reload since item removed");
        });

        await _bookmarksApi.OnChanged.AddListener(async (s, info) =>
        {
            if (!string.IsNullOrWhiteSpace(info.Url) &&
                !string.IsNullOrWhiteSpace(info.Title))
            {
                await _bkManager.UpdateTitleAsync(info.Url, info.Title);
            }

            _logger.LogInformation("Bookmark data reload since item changed");
        });

        await _bookmarksApi.OnCreated.AddListener(async (s, node) =>
        {
            if (!string.IsNullOrWhiteSpace(node.Url) &&
                !string.IsNullOrWhiteSpace(node.Title))
            {
                var tags         = new HashSet <string>();
                var nodes        = _bookmarksApi.GetAllParentAsync(node.ParentId);
                var deepth       = 0;
                var parentOffset = 0;
                await foreach (var parentNode in nodes)
                {
                    if (deepth == 0)
                    {
                        parentOffset = parentNode.Index ?? 0;
                    }
                    if (!string.IsNullOrWhiteSpace(parentNode.Title) &&
                        !Consts.IsReservedBookmarkFolder(parentNode.Title))
                    {
                        deepth++;
                        tags.Add(parentNode.Title);
                    }
                }
                await _bkManager.AppendBookmarksAsync(new[] { new BookmarkNode(node)
                                                              {
                                                                  Deepth           = deepth + 1,
                                                                  ParentNodeOffset = parentOffset,
                                                                  Tags             = tags.ToList()
                                                              } });
            }

            _logger.LogInformation("Bookmark data reload since item added");
        });

        await _bookmarksApi.OnMoved.AddListener(async (s, info) =>
        {
            var tags         = new HashSet <string>();
            var node         = (await _bookmarksApi.Get(s)).FirstOrDefault();
            var nodes        = _bookmarksApi.GetAllParentAsync(node.ParentId);
            var deepth       = 0;
            var parentOffset = 0;
            await foreach (var parentNode in nodes)
            {
                if (deepth == 0)
                {
                    parentOffset = parentNode.Index ?? 0;
                }
                if (!string.IsNullOrWhiteSpace(parentNode.Title) &&
                    !Consts.IsReservedBookmarkFolder(parentNode.Title))
                {
                    deepth++;
                    tags.Add(parentNode.Title);
                }
            }
            if (!string.IsNullOrWhiteSpace(node.Url) &&
                !string.IsNullOrWhiteSpace(node.Title))
            {
                await _bkManager.UpdatePositionAsync(node.Url, tags.ToList(), deepth + 1, parentOffset, node.Index ?? 0);
            }
        });

        Task.Run(async() =>
        {
            await Task.Delay(TimeSpan.FromSeconds(1));
            var all = await GetAllBookmarkAsync();
            _logger.LogInformation("Found {Count} bookmarks, try to load them", all.Count);
            // make init order look like bookmarks tree
            await _bkManager.AppendBookmarksAsync(all);
        });
    }