mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 02:18:27 +03:00
tree node traversal for folder
This commit is contained in:
parent
4b3bae5797
commit
18f04af051
6 changed files with 115 additions and 10 deletions
8
src/Core/Models/Domain/ITreeNodeObject.cs
Normal file
8
src/Core/Models/Domain/ITreeNodeObject.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Bit.Core.Models.Domain
|
||||||
|
{
|
||||||
|
public interface ITreeNodeObject
|
||||||
|
{
|
||||||
|
string Id { get; set; }
|
||||||
|
string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
18
src/Core/Models/Domain/TreeNode.cs
Normal file
18
src/Core/Models/Domain/TreeNode.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Domain
|
||||||
|
{
|
||||||
|
public class TreeNode<T> where T : ITreeNodeObject
|
||||||
|
{
|
||||||
|
public T Parent { get; set; }
|
||||||
|
public T Node { get; set; }
|
||||||
|
public List<TreeNode<T>> Children { get; set; }
|
||||||
|
|
||||||
|
public TreeNode(T node, string name, T parent)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
Node = node;
|
||||||
|
Node.Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Bit.Core.Models.View
|
namespace Bit.Core.Models.View
|
||||||
{
|
{
|
||||||
public class CollectionView : View
|
public class CollectionView : View, ITreeNodeObject
|
||||||
{
|
{
|
||||||
public CollectionView() { }
|
public CollectionView() { }
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
||||||
|
|
||||||
namespace Bit.Core.Models.View
|
namespace Bit.Core.Models.View
|
||||||
{
|
{
|
||||||
public class FolderView : View
|
public class FolderView : View, ITreeNodeObject
|
||||||
{
|
{
|
||||||
public FolderView() { }
|
public FolderView() { }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Exceptions;
|
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Request;
|
using Bit.Core.Models.Request;
|
||||||
|
@ -9,10 +7,7 @@ using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
|
@ -21,7 +16,7 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
private const string Keys_CiphersFormat = "ciphers_{0}";
|
private const string Keys_CiphersFormat = "ciphers_{0}";
|
||||||
private const string Keys_FoldersFormat = "folders_{0}";
|
private const string Keys_FoldersFormat = "folders_{0}";
|
||||||
private const string NestingDelimiter = "/";
|
private const char NestingDelimiter = '/';
|
||||||
|
|
||||||
private List<FolderView> _decryptedFolderCache;
|
private List<FolderView> _decryptedFolderCache;
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
|
@ -115,7 +110,28 @@ namespace Bit.Core.Services
|
||||||
return _decryptedFolderCache;
|
return _decryptedFolderCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: nested stuff
|
public async Task<List<TreeNode<FolderView>>> GetAllNestedAsync()
|
||||||
|
{
|
||||||
|
var folders = await GetAllDecryptedAsync();
|
||||||
|
var nodes = new List<TreeNode<FolderView>>();
|
||||||
|
foreach(var f in folders)
|
||||||
|
{
|
||||||
|
var folderCopy = new FolderView
|
||||||
|
{
|
||||||
|
Id = f.Id,
|
||||||
|
RevisionDate = f.RevisionDate
|
||||||
|
};
|
||||||
|
CoreHelpers.NestedTraverse(nodes, 0, f.Name.Split(NestingDelimiter), folderCopy, null,
|
||||||
|
NestingDelimiter);
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TreeNode<FolderView>> GetNestedAsync(string id)
|
||||||
|
{
|
||||||
|
var folders = await GetAllNestedAsync();
|
||||||
|
return CoreHelpers.GetTreeNodeObject(folders, id);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SaveWithServerAsync(Folder folder)
|
public async Task SaveWithServerAsync(Folder folder)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
using System;
|
using Bit.Core.Models.Domain;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Bit.Core.Utilities
|
namespace Bit.Core.Utilities
|
||||||
|
@ -87,5 +90,65 @@ namespace Bit.Core.Utilities
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void NestedTraverse<T>(List<TreeNode<T>> nodeTree, int partIndex, string[] parts,
|
||||||
|
T obj, T parent, char delimiter) where T : ITreeNodeObject
|
||||||
|
{
|
||||||
|
if(parts.Length <= partIndex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var end = partIndex == parts.Length - 1;
|
||||||
|
var partName = parts[partIndex];
|
||||||
|
foreach(var n in nodeTree)
|
||||||
|
{
|
||||||
|
if(n.Node.Name != parts[partIndex])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(end && n.Node.Id != obj.Id)
|
||||||
|
{
|
||||||
|
// Another node with the same name.
|
||||||
|
nodeTree.Add(new TreeNode<T>(obj, partName, parent));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NestedTraverse(n.Children, partIndex + 1, parts, obj, n.Node, delimiter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!nodeTree.Any(n => n.Node.Name == partName))
|
||||||
|
{
|
||||||
|
if(end)
|
||||||
|
{
|
||||||
|
nodeTree.Add(new TreeNode<T>(obj, partName, parent));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var newPartName = string.Concat(parts[partIndex], delimiter, parts[partIndex + 1]);
|
||||||
|
var newParts = new List<string> { newPartName };
|
||||||
|
var newPartsStartFrom = partIndex + 2;
|
||||||
|
newParts.AddRange(new ArraySegment<string>(parts, newPartsStartFrom, parts.Length - newPartsStartFrom));
|
||||||
|
NestedTraverse(nodeTree, 0, newParts.ToArray(), obj, parent, delimiter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TreeNode<T> GetTreeNodeObject<T>(List<TreeNode<T>> nodeTree, string id) where T : ITreeNodeObject
|
||||||
|
{
|
||||||
|
foreach(var n in nodeTree)
|
||||||
|
{
|
||||||
|
if(n.Node.Id == id)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
else if(n.Children != null)
|
||||||
|
{
|
||||||
|
var node = GetTreeNodeObject(n.Children, id);
|
||||||
|
if(node != null)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue