internal void AddItem(Item itemInfo) { var item = CloudItem.FromTemplate(itemInfo, _owner); _items.Add(item); // Link with parent if possible. if (item.IsShareRoot) { _shares.Add(item); // Pretend it has no parent, since share root parents are going to be external to the current filesystem. item.ParentID = null; } else if (item.ParentID != null) { item.Parent = AllItems.FirstOrDefault(i => i.ID == item.ParentID); if (item.Parent != null) { item.Parent.Children = item.Parent.Children.Add(item); } else { // The parent is not a part of the current filesystem. Weird, huh? _orphans.Add(item); } } else { _roots.Add(item); } // Is this maybe a parent to any orphan item? foreach (var orphan in _orphans) { if (orphan.ParentID == item.ID) { orphan.Parent = item; item.Children.Add(orphan); } } // Remove any orhpans we de-orphaned. _orphans.RemoveAll(o => o.Parent != null); // Is it a special item? if (item.Type == ItemType.Files) Files = item; else if (item.Type == ItemType.Inbox) Inbox = item; else if (item.Type == ItemType.Trash) Trash = item; }
/// <summary> /// Materializes an instance from an Item structure returned by the Mega API, treated as a template for this item. /// Parent-child relationships are not automatically linked up - that is left up to the creator. /// </summary> internal static CloudItem FromTemplate(Item template, MegaClient client) { Argument.ValidateIsNotNull(template, "template"); Argument.ValidateIsNotNull(client, "client"); CloudItem item = new CloudItem(client) { TypeID = template.Type, // Filter out invalid sizes that Mega does not work with (anything less than 1). Size = template.Size.GetValueOrDefault() > 0 ? (long?)template.Size.Value : null, ID = template.ID, OwnerID = template.OwnerID, LastUpdated = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(template.Timestamp).ToLocalTime(), ParentID = template.ParentID, EncryptedKeys = template.EncryptedKeys.ToImmutableHashSet(), IsShareRoot = template.ShareKey.HasValue }; bool hasEncryptedData = true; switch (template.Type) { case KnownItemTypes.File: item.Type = ItemType.File; break; case KnownItemTypes.Folder: item.Type = ItemType.Folder; break; case KnownItemTypes.Inbox: item.Type = ItemType.Inbox; hasEncryptedData = false; break; case KnownItemTypes.Trash: item.Type = ItemType.Trash; hasEncryptedData = false; break; case KnownItemTypes.Files: item.Type = ItemType.Files; hasEncryptedData = false; break; default: item.Type = ItemType.Unknown; break; } if (hasEncryptedData) { // Decrypt the item attributes, if the item has them and if we have a key. var itemKey = client.DecryptItemKey(item.EncryptedKeys); // We have a key for this item! var attributesKey = Algorithms.DeriveNodeAttributesKey(itemKey); item.Attributes = ItemAttributes.DecryptAndDeserialize(template.Attributes, attributesKey); } return item; }
private async Task DeleteUnwantedItems(CloudItem rootDirectory, ICollection<OpaqueID> wantedItems, IFeedbackChannel feedback) { foreach (var ci in rootDirectory.Children) { if (!wantedItems.Contains(ci.ID)) { await ci.DeleteAsync(feedback); continue; } // If it is a wanted item, it might not have wanted children, so delete them. if (ci.Type == ItemType.Folder) await DeleteUnwantedItems(ci, wantedItems, feedback); } }
/// <summary> /// Moves the item under another item. This operation is valid for files and folders. /// The parent is not updated in any existing filesystem snapshot. /// </summary> /// <param name="newParent">The new parent of the item.</param> /// <param name="feedbackChannel">Allows you to receive feedback about the operation while it is running.</param> /// <param name="cancellationToken">Allows you to cancel the operation.</param> public async Task MoveAsync(CloudItem newParent, IFeedbackChannel feedbackChannel = null, CancellationToken cancellationToken = default(CancellationToken)) { Argument.ValidateIsNotNull(newParent, "newParent"); if (Type != ItemType.File && Type != ItemType.Folder) throw new InvalidOperationException("You can only move files or folders."); if (!newParent.IsContainer) throw new InvalidOperationException("The specified destination cannot contain other items."); PatternHelper.LogMethodCall("MoveAsync", feedbackChannel, cancellationToken); PatternHelper.EnsureFeedbackChannel(ref feedbackChannel); using (await _client.AcquireLock(feedbackChannel, cancellationToken)) { await _client.ExecuteCommandInternalAsync<SuccessResult>(feedbackChannel, cancellationToken, new MoveItemCommand { ClientInstanceID = _client._clientInstanceID, ItemID = ID, ParentID = newParent.ID }); _client.InvalidateFilesystemInternal(); } }