Skip to content

Commit db70e42

Browse files
authored
Code Quality: Improved app startup routine (#12861)
1 parent 6b0cd1f commit db70e42

File tree

114 files changed

+1371
-957
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+1371
-957
lines changed

src/Files.App.Storage/FtpStorage/FtpStorable.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
11
// Copyright (c) 2023 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Files.Core.Storage;
45
using Files.Core.Storage.LocatableStorage;
5-
using Files.Shared.Helpers;
6+
using Files.Core.Storage.NestedStorage;
67
using FluentFTP;
78
using System.Threading;
89
using System.Threading.Tasks;
910

1011
namespace Files.App.Storage.FtpStorage
1112
{
12-
public abstract class FtpStorable : ILocatableStorable
13+
public abstract class FtpStorable : ILocatableStorable, INestedStorable
1314
{
14-
private string? _computedId;
15-
1615
/// <inheritdoc/>
17-
public string Path { get; protected set; }
16+
public virtual string Path { get; protected set; }
1817

1918
/// <inheritdoc/>
20-
public string Name { get; protected set; }
19+
public virtual string Name { get; protected set; }
2120

2221
/// <inheritdoc/>
23-
public virtual string Id => _computedId ??= ChecksumHelpers.CalculateChecksumForPath(Path);
22+
public virtual string Id { get; }
23+
24+
/// <summary>
25+
/// Gets the parent folder of the storable, if any.
26+
/// </summary>
27+
protected virtual IFolder? Parent { get; }
2428

25-
protected internal FtpStorable(string path, string name)
29+
protected internal FtpStorable(string path, string name, IFolder? parent)
2630
{
2731
Path = FtpHelpers.GetFtpPath(path);
2832
Name = name;
33+
Id = Path;
34+
Parent = parent;
2935
}
3036

3137
/// <inheritdoc/>
32-
public virtual Task<ILocatableFolder?> GetParentAsync(CancellationToken cancellationToken = default)
38+
public Task<IFolder?> GetParentAsync(CancellationToken cancellationToken = default)
3339
{
34-
return Task.FromResult<ILocatableFolder?>(null);
40+
return Task.FromResult<IFolder?>(Parent);
3541
}
3642

3743
protected AsyncFtpClient GetFtpClient()
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
// Copyright (c) 2023 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Files.Core.Storage;
45
using Files.Core.Storage.LocatableStorage;
56
using Files.Core.Storage.ModifiableStorage;
7+
using Files.Core.Storage.NestedStorage;
68
using System;
79
using System.IO;
810
using System.Threading;
911
using System.Threading.Tasks;
1012

1113
namespace Files.App.Storage.FtpStorage
1214
{
13-
public sealed class FtpStorageFile : FtpStorable, IModifiableFile, ILocatableFile
15+
public sealed class FtpStorageFile : FtpStorable, IModifiableFile, ILocatableFile, INestedFile
1416
{
15-
public FtpStorageFile(string path, string name)
16-
: base(path, name)
17+
public FtpStorageFile(string path, string name, IFolder? parent)
18+
: base(path, name, parent)
1719
{
1820
}
1921

@@ -24,17 +26,11 @@ public async Task<Stream> OpenStreamAsync(FileAccess access, CancellationToken c
2426
await ftpClient.EnsureConnectedAsync(cancellationToken);
2527

2628
if (access.HasFlag(FileAccess.Write))
27-
{
2829
return await ftpClient.OpenWrite(Path, token: cancellationToken);
29-
}
3030
else if (access.HasFlag(FileAccess.Read))
31-
{
3231
return await ftpClient.OpenRead(Path, token: cancellationToken);
33-
}
3432
else
35-
{
3633
throw new ArgumentException($"Invalid {nameof(access)} flag.");
37-
}
3834
}
3935
}
4036
}

src/Files.App.Storage/FtpStorage/FtpStorageFolder.cs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
// Licensed under the MIT License. See the LICENSE.
33

44
using Files.Core.Storage;
5+
using Files.Core.Storage.DirectStorage;
56
using Files.Core.Storage.Enums;
7+
using Files.Core.Storage.ExtendableStorage;
68
using Files.Core.Storage.Extensions;
79
using Files.Core.Storage.LocatableStorage;
810
using Files.Core.Storage.ModifiableStorage;
11+
using Files.Core.Storage.NestedStorage;
912
using Files.Shared.Helpers;
1013
using FluentFTP;
1114
using System;
@@ -17,15 +20,15 @@
1720

1821
namespace Files.App.Storage.FtpStorage
1922
{
20-
public sealed class FtpStorageFolder : FtpStorable, ILocatableFolder, IModifiableFolder
23+
public sealed class FtpStorageFolder : FtpStorable, ILocatableFolder, IModifiableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
2124
{
22-
public FtpStorageFolder(string path, string name)
23-
: base(path, name)
25+
public FtpStorageFolder(string path, string name, IFolder? parent)
26+
: base(path, name, parent)
2427
{
2528
}
2629

2730
/// <inheritdoc/>
28-
public async Task<IFile> GetFileAsync(string fileName, CancellationToken cancellationToken = default)
31+
public async Task<INestedFile> GetFileAsync(string fileName, CancellationToken cancellationToken = default)
2932
{
3033
using var ftpClient = GetFtpClient();
3134
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -36,11 +39,11 @@ public async Task<IFile> GetFileAsync(string fileName, CancellationToken cancell
3639
if (item is null || item.Type != FtpObjectType.File)
3740
throw new FileNotFoundException();
3841

39-
return new FtpStorageFile(path, item.Name);
42+
return new FtpStorageFile(path, item.Name, this);
4043
}
4144

4245
/// <inheritdoc/>
43-
public async Task<IFolder> GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
46+
public async Task<INestedFolder> GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
4447
{
4548
using var ftpClient = GetFtpClient();
4649
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -51,11 +54,11 @@ public async Task<IFolder> GetFolderAsync(string folderName, CancellationToken c
5154
if (item is null || item.Type != FtpObjectType.Directory)
5255
throw new DirectoryNotFoundException();
5356

54-
return new FtpStorageFolder(path, item.Name);
57+
return new FtpStorageFolder(path, item.Name, this);
5558
}
5659

5760
/// <inheritdoc/>
58-
public async IAsyncEnumerable<IStorable> GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
61+
public async IAsyncEnumerable<INestedStorable> GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
5962
{
6063
using var ftpClient = GetFtpClient();
6164
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -65,32 +68,32 @@ public async IAsyncEnumerable<IStorable> GetItemsAsync(StorableKind kind = Stora
6568
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
6669
{
6770
if (item.Type == FtpObjectType.File)
68-
yield return new FtpStorageFile(item.FullName, item.Name);
71+
yield return new FtpStorageFile(item.FullName, item.Name, this);
6972
}
7073
}
7174
else if (kind == StorableKind.Folders)
7275
{
7376
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
7477
{
7578
if (item.Type == FtpObjectType.Directory)
76-
yield return new FtpStorageFolder(item.FullName, item.Name);
79+
yield return new FtpStorageFolder(item.FullName, item.Name, this);
7780
}
7881
}
7982
else
8083
{
8184
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
8285
{
8386
if (item.Type == FtpObjectType.File)
84-
yield return new FtpStorageFile(item.FullName, item.Name);
87+
yield return new FtpStorageFile(item.FullName, item.Name, this);
8588

8689
if (item.Type == FtpObjectType.Directory)
87-
yield return new FtpStorageFolder(item.FullName, item.Name);
90+
yield return new FtpStorageFolder(item.FullName, item.Name, this);
8891
}
8992
}
9093
}
9194

9295
/// <inheritdoc/>
93-
public async Task DeleteAsync(IStorable item, bool permanently = false, CancellationToken cancellationToken = default)
96+
public async Task DeleteAsync(INestedStorable item, bool permanently = false, CancellationToken cancellationToken = default)
9497
{
9598
using var ftpClient = GetFtpClient();
9699
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -110,11 +113,11 @@ public async Task DeleteAsync(IStorable item, bool permanently = false, Cancella
110113
}
111114

112115
/// <inheritdoc/>
113-
public async Task<IStorable> CreateCopyOfAsync(IStorable itemToCopy, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
116+
public async Task<INestedStorable> CreateCopyOfAsync(INestedStorable itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default)
114117
{
115118
if (itemToCopy is IFile sourceFile)
116119
{
117-
var copiedFile = await CreateFileAsync(itemToCopy.Name, collisionOption, cancellationToken);
120+
var copiedFile = await CreateFileAsync(itemToCopy.Name, overwrite, cancellationToken);
118121
await sourceFile.CopyContentsToAsync(copiedFile, cancellationToken);
119122

120123
return copiedFile;
@@ -126,41 +129,34 @@ public async Task<IStorable> CreateCopyOfAsync(IStorable itemToCopy, CreationCol
126129
}
127130

128131
/// <inheritdoc/>
129-
public async Task<IStorable> MoveFromAsync(IStorable itemToMove, IModifiableFolder source, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
132+
public async Task<INestedStorable> MoveFromAsync(INestedStorable itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default)
130133
{
131134
using var ftpClient = GetFtpClient();
132135
await ftpClient.EnsureConnectedAsync(cancellationToken);
133136

134-
var newItem = await CreateCopyOfAsync(itemToMove, collisionOption, cancellationToken);
137+
var newItem = await CreateCopyOfAsync(itemToMove, overwrite, cancellationToken);
135138
await source.DeleteAsync(itemToMove, true, cancellationToken);
136139

137140
return newItem;
138141
}
139142

140143
/// <inheritdoc/>
141-
public async Task<IFile> CreateFileAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
144+
public async Task<INestedFile> CreateFileAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
142145
{
143146
using var ftpClient = GetFtpClient();
144147
await ftpClient.EnsureConnectedAsync(cancellationToken);
145148

146149
var newPath = $"{Path}/{desiredName}";
147-
if (await ftpClient.FileExists(newPath, cancellationToken))
148-
{
149-
if (collisionOption == CreationCollisionOption.FailIfExists)
150-
throw new IOException("File already exists.");
151-
152-
if (collisionOption == CreationCollisionOption.OpenIfExists)
153-
return new FtpStorageFile(newPath, desiredName);
154-
}
150+
if (overwrite && await ftpClient.FileExists(newPath, cancellationToken))
151+
throw new IOException("File already exists.");
155152

156153
using var stream = new MemoryStream();
157-
var replaceExisting = collisionOption == CreationCollisionOption.ReplaceExisting;
158-
var result = await ftpClient.UploadStream(stream, newPath, replaceExisting ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip, token: cancellationToken);
154+
var result = await ftpClient.UploadStream(stream, newPath, overwrite ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip, token: cancellationToken);
159155

160156
if (result == FtpStatus.Success)
161157
{
162158
// Success
163-
return new FtpStorageFile(newPath, desiredName);
159+
return new FtpStorageFile(newPath, desiredName, this);
164160
}
165161
else if (result == FtpStatus.Skipped)
166162
{
@@ -175,27 +171,20 @@ public async Task<IFile> CreateFileAsync(string desiredName, CreationCollisionOp
175171
}
176172

177173
/// <inheritdoc/>
178-
public async Task<IFolder> CreateFolderAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
174+
public async Task<INestedFolder> CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
179175
{
180176
using var ftpClient = GetFtpClient();
181177
await ftpClient.EnsureConnectedAsync(cancellationToken);
182178

183179
var newPath = $"{Path}/{desiredName}";
184-
if (await ftpClient.DirectoryExists(newPath, cancellationToken))
185-
{
186-
if (collisionOption == CreationCollisionOption.FailIfExists)
187-
throw new IOException("Directory already exists.");
188-
189-
if (collisionOption == CreationCollisionOption.OpenIfExists)
190-
return new FtpStorageFolder(newPath, desiredName);
191-
}
180+
if (overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))
181+
throw new IOException("Directory already exists.");
192182

193-
var replaceExisting = collisionOption == CreationCollisionOption.ReplaceExisting;
194-
var isSuccessful = await ftpClient.CreateDirectory(newPath, replaceExisting, cancellationToken);
183+
var isSuccessful = await ftpClient.CreateDirectory(newPath, overwrite, cancellationToken);
195184
if (!isSuccessful)
196185
throw new IOException("Directory was not successfully created.");
197186

198-
return new FtpStorageFolder(newPath, desiredName);
187+
return new FtpStorageFolder(newPath, desiredName, this);
199188
}
200189
}
201190
}

src/Files.App.Storage/FtpStorage/FtpStorageService.cs

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,41 @@
44
using Files.Core.Storage;
55
using Files.Core.Storage.LocatableStorage;
66
using FluentFTP;
7-
using System;
87
using System.IO;
98
using System.Threading;
109
using System.Threading.Tasks;
1110

1211
namespace Files.App.Storage.FtpStorage
1312
{
13+
/// <inheritdoc cref="IFtpStorageService"/>
1414
public sealed class FtpStorageService : IFtpStorageService
1515
{
16-
public Task<bool> IsAccessibleAsync(CancellationToken cancellationToken = default)
16+
/// <inheritdoc/>
17+
public async Task<IFolder> GetFolderAsync(string id, CancellationToken cancellationToken = default)
1718
{
18-
return Task.FromResult(true); // TODO: Check if FTP is available
19-
}
20-
21-
public async Task<bool> FileExistsAsync(string path, CancellationToken cancellationToken = default)
22-
{
23-
try
24-
{
25-
_ = await GetFileFromPathAsync(path, cancellationToken);
26-
return true;
27-
}
28-
catch (Exception)
29-
{
30-
return false;
31-
}
32-
}
33-
34-
public async Task<bool> DirectoryExistsAsync(string path, CancellationToken cancellationToken = default)
35-
{
36-
try
37-
{
38-
_ = await GetFolderFromPathAsync(path, cancellationToken);
39-
return true;
40-
}
41-
catch (Exception)
42-
{
43-
return false;
44-
}
45-
}
46-
47-
public async Task<ILocatableFolder> GetFolderFromPathAsync(string path, CancellationToken cancellationToken = default)
48-
{
49-
using var ftpClient = FtpHelpers.GetFtpClient(path);
19+
using var ftpClient = FtpHelpers.GetFtpClient(id);
5020
await ftpClient.EnsureConnectedAsync(cancellationToken);
5121

52-
var ftpPath = FtpHelpers.GetFtpPath(path);
22+
var ftpPath = FtpHelpers.GetFtpPath(id);
5323
var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
5424
if (item is null || item.Type != FtpObjectType.Directory)
5525
throw new DirectoryNotFoundException("Directory was not found from path.");
5626

57-
return new FtpStorageFolder(ftpPath, item.Name);
27+
return new FtpStorageFolder(ftpPath, item.Name, null);
5828
}
5929

60-
public async Task<ILocatableFile> GetFileFromPathAsync(string path, CancellationToken cancellationToken = default)
30+
/// <inheritdoc/>
31+
public async Task<IFile> GetFileAsync(string id, CancellationToken cancellationToken = default)
6132
{
62-
using var ftpClient = FtpHelpers.GetFtpClient(path);
33+
using var ftpClient = FtpHelpers.GetFtpClient(id);
6334
await ftpClient.EnsureConnectedAsync(cancellationToken);
6435

65-
var ftpPath = FtpHelpers.GetFtpPath(path);
36+
var ftpPath = FtpHelpers.GetFtpPath(id);
6637
var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
6738
if (item is null || item.Type != FtpObjectType.File)
6839
throw new FileNotFoundException("File was not found from path.");
6940

70-
return new FtpStorageFile(ftpPath, item.Name);
41+
return new FtpStorageFile(ftpPath, item.Name, null);
7142
}
7243
}
7344
}

0 commit comments

Comments
 (0)