Skip to content

Commit 2d51a3d

Browse files
authored
Introduce abstract storage layer (#9544)
1 parent f3d72eb commit 2d51a3d

Some content is hidden

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

49 files changed

+1600
-38
lines changed

Files.sln

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
2-
# Visual Studio Version 16
3-
VisualStudioVersion = 16.0.31911.196
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.1.32421.90
44
MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Files.FullTrust", "src\Files.FullTrust\Files.FullTrust.csproj", "{533F9E86-EE0A-4FCB-B70C-F29532C1B787}"
66
ProjectSection(ProjectDependencies) = postProject
@@ -26,12 +26,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A74DCE98-A74
2626
EndProject
2727
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{481DE2EA-E6CE-4A9C-A220-3B543B95AAA1}"
2828
EndProject
29-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Files.UI", "Files.UI", "{A188C26B-E731-4E0B-9D17-D21CEBD9B43F}"
29+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{A188C26B-E731-4E0B-9D17-D21CEBD9B43F}"
3030
EndProject
3131
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Files.Backend", "src\Files.Backend\Files.Backend.csproj", "{4CFE0BBC-8D07-49A0-8B10-4EDD61ABCF57}"
3232
EndProject
3333
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilesLauncher", "src\Files.OpenDialog\FilesLauncher\FilesLauncher.vcxproj", "{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}"
3434
EndProject
35+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{9F36C2AD-005D-4EA5-A1F1-6BC42773FC85}"
36+
EndProject
37+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Files.Sdk.Storage", "src\Files.Sdk.Storage\Files.Sdk.Storage.csproj", "{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}"
38+
EndProject
39+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Files.Uwp.Storage", "src\Files.Uwp.Storage\Files.Uwp.Storage.csproj", "{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}"
40+
EndProject
3541
Global
3642
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3743
Debug|arm64 = Debug|arm64
@@ -156,12 +162,12 @@ Global
156162
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Release|x64.Build.0 = Release|x64
157163
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Release|x86.ActiveCfg = Release|Win32
158164
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Release|x86.Build.0 = Release|Win32
159-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|arm64.ActiveCfg = Release|arm64
160-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|arm64.Build.0 = Release|arm64
161-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x64.ActiveCfg = Release|x64
162-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x64.Build.0 = Release|x64
163-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x86.ActiveCfg = Release|Win32
164-
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x86.Build.0 = Release|Win32
165+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|arm64.ActiveCfg = Sideload|arm64
166+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|arm64.Build.0 = Sideload|arm64
167+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x64.ActiveCfg = Sideload|x64
168+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x64.Build.0 = Sideload|x64
169+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x86.ActiveCfg = Sideload|Win32
170+
{A2FF3F3B-8EBC-4108-B99D-1476B7876656}.Sideload|x86.Build.0 = Sideload|Win32
165171
{B7E43D1F-AC8B-4958-95D5-A06CDD1FEACD}.Debug|arm64.ActiveCfg = Debug|Any CPU
166172
{B7E43D1F-AC8B-4958-95D5-A06CDD1FEACD}.Debug|arm64.Build.0 = Debug|Any CPU
167173
{B7E43D1F-AC8B-4958-95D5-A06CDD1FEACD}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -210,12 +216,48 @@ Global
210216
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Release|x64.Build.0 = Release|x64
211217
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Release|x86.ActiveCfg = Release|Win32
212218
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Release|x86.Build.0 = Release|Win32
213-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|arm64.ActiveCfg = Release|arm64
214-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|arm64.Build.0 = Release|arm64
215-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x64.ActiveCfg = Debug|x64
216-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x64.Build.0 = Debug|x64
217-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x86.ActiveCfg = Release|Win32
218-
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x86.Build.0 = Release|Win32
219+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|arm64.ActiveCfg = Sideload|arm64
220+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|arm64.Build.0 = Sideload|arm64
221+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x64.ActiveCfg = Sideload|x64
222+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x64.Build.0 = Sideload|x64
223+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x86.ActiveCfg = Sideload|Win32
224+
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07}.Sideload|x86.Build.0 = Sideload|Win32
225+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|arm64.ActiveCfg = Debug|arm64
226+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|arm64.Build.0 = Debug|arm64
227+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|x64.ActiveCfg = Debug|x64
228+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|x64.Build.0 = Debug|x64
229+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|x86.ActiveCfg = Debug|x86
230+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Debug|x86.Build.0 = Debug|x86
231+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|arm64.ActiveCfg = Release|arm64
232+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|arm64.Build.0 = Release|arm64
233+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|x64.ActiveCfg = Release|x64
234+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|x64.Build.0 = Release|x64
235+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|x86.ActiveCfg = Release|x86
236+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Release|x86.Build.0 = Release|x86
237+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|arm64.ActiveCfg = Sideload|arm64
238+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|arm64.Build.0 = Sideload|arm64
239+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|x64.ActiveCfg = Sideload|x64
240+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|x64.Build.0 = Sideload|x64
241+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|x86.ActiveCfg = Sideload|x86
242+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79}.Sideload|x86.Build.0 = Sideload|x86
243+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|arm64.ActiveCfg = Debug|arm64
244+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|arm64.Build.0 = Debug|arm64
245+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|x64.ActiveCfg = Debug|x64
246+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|x64.Build.0 = Debug|x64
247+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|x86.ActiveCfg = Debug|x86
248+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Debug|x86.Build.0 = Debug|x86
249+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|arm64.ActiveCfg = Release|arm64
250+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|arm64.Build.0 = Release|arm64
251+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|x64.ActiveCfg = Release|x64
252+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|x64.Build.0 = Release|x64
253+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|x86.ActiveCfg = Release|x86
254+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Release|x86.Build.0 = Release|x86
255+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|arm64.ActiveCfg = Sideload|arm64
256+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|arm64.Build.0 = Sideload|arm64
257+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|x64.ActiveCfg = Sideload|x64
258+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|x64.Build.0 = Sideload|x64
259+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|x86.ActiveCfg = Sideload|x86
260+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7}.Sideload|x86.Build.0 = Sideload|x86
219261
EndGlobalSection
220262
GlobalSection(SolutionProperties) = preSolution
221263
HideSolutionNode = FALSE
@@ -230,8 +272,11 @@ Global
230272
{A2FF3F3B-8EBC-4108-B99D-1476B7876656} = {0175B70C-1E29-4A3F-AA4F-C2017B040EF0}
231273
{B7E43D1F-AC8B-4958-95D5-A06CDD1FEACD} = {481DE2EA-E6CE-4A9C-A220-3B543B95AAA1}
232274
{A188C26B-E731-4E0B-9D17-D21CEBD9B43F} = {A74DCE98-A744-4D71-A2B1-7EE4FED0936B}
233-
{4CFE0BBC-8D07-49A0-8B10-4EDD61ABCF57} = {A188C26B-E731-4E0B-9D17-D21CEBD9B43F}
275+
{4CFE0BBC-8D07-49A0-8B10-4EDD61ABCF57} = {9F36C2AD-005D-4EA5-A1F1-6BC42773FC85}
234276
{25FD5045-6D4C-4DD0-B3AC-613AB59CBB07} = {0175B70C-1E29-4A3F-AA4F-C2017B040EF0}
277+
{9F36C2AD-005D-4EA5-A1F1-6BC42773FC85} = {A74DCE98-A744-4D71-A2B1-7EE4FED0936B}
278+
{93B7A21C-A6CA-4A21-A69C-B5BD26BDDB79} = {9F36C2AD-005D-4EA5-A1F1-6BC42773FC85}
279+
{DEDFB63C-7A8D-4E1F-A143-7B61CAC1F2A7} = {A188C26B-E731-4E0B-9D17-D21CEBD9B43F}
235280
EndGlobalSection
236281
GlobalSection(ExtensibilityGlobals) = postSolution
237282
SolutionGuid = {0E62043C-A7A1-4982-9EC9-4CDB2939B776}

src/Files.Backend/Files.Backend.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
</ItemGroup>
1818

1919
<ItemGroup>
20+
<ProjectReference Include="..\Files.Sdk.Storage\Files.Sdk.Storage.csproj" />
2021
<ProjectReference Include="..\Files.Shared\Files.Shared.csproj" />
2122
</ItemGroup>
2223

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Files.Sdk.Storage.LocatableStorage;
5+
6+
namespace Files.Backend.Services
7+
{
8+
/// <summary>
9+
/// A service that interacts with the system file explorer.
10+
/// </summary>
11+
public interface IFileExplorerService
12+
{
13+
/// <summary>
14+
/// Opens the app folder.
15+
/// </summary>
16+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
17+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
18+
Task OpenAppFolderAsync(CancellationToken cancellationToken = default);
19+
20+
/// <summary>
21+
/// Opens provided <paramref name="folder"/> in file explorer.
22+
/// </summary>
23+
/// <param name="folder">The folder to open file explorer in.</param>
24+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
25+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
26+
Task OpenInFileExplorerAsync(ILocatableFolder folder, CancellationToken cancellationToken = default);
27+
28+
/// <summary>
29+
/// Awaits the user input and picks single file from the file explorer dialog.
30+
/// </summary>
31+
/// <param name="filter">The filter to apply when picking files.</param>
32+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
33+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. If successful and a file has been picked, returns <see cref="ILocatableFile"/>, otherwise null.</returns>
34+
Task<ILocatableFile?> PickSingleFileAsync(IEnumerable<string>? filter, CancellationToken cancellationToken = default);
35+
36+
/// <summary>
37+
/// Awaits the user input and picks single folder from the file explorer dialog.
38+
/// </summary>
39+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
40+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. If successful and a folder has been picked, returns <see cref="ILocatableFolder"/>, otherwise null.</returns>
41+
Task<ILocatableFolder?> PickSingleFolderAsync(CancellationToken cancellationToken = default);
42+
}
43+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Files.Sdk.Storage.Enums
2+
{
3+
public enum CreationCollisionOption : byte
4+
{
5+
GenerateUniqueName = 0,
6+
ReplaceExisting = 1,
7+
OpenIfExists = 2,
8+
FailIfExists = 3,
9+
}
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Files.Sdk.Storage.Enums
2+
{
3+
public enum NameCollisionOption : byte
4+
{
5+
GenerateUniqueName = 0,
6+
ReplaceExisting = 1,
7+
FailIfExists = 2
8+
}
9+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace Files.Sdk.Storage.Enums
4+
{
5+
[Flags]
6+
public enum StorableKind : byte
7+
{
8+
None = 0,
9+
Files = 1,
10+
Folders = 2,
11+
All = Files | Folders
12+
}
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.IO;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Files.Sdk.Storage.Extensions
6+
{
7+
public static class StorageExtensions
8+
{
9+
public static async Task CopyContentsToAsync(this IFile source, IFile destination, CancellationToken cancellationToken = default)
10+
{
11+
// Internal Stream.GetCopyBufferSize() - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs
12+
const int DEFAULT_COPY_BUFFER_SIZE = 81920;
13+
14+
using var sourceStream = await source.OpenStreamAsync(FileAccess.Read, FileShare.Read, cancellationToken);
15+
using var destinationStream = await destination.OpenStreamAsync(FileAccess.Read, FileShare.None, cancellationToken);
16+
17+
await sourceStream.CopyToAsync(destinationStream, DEFAULT_COPY_BUFFER_SIZE, cancellationToken);
18+
}
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<Platforms>x86;x64;arm64</Platforms>
6+
<RuntimeIdentifiers>win-arm64;win-x86;win-x64</RuntimeIdentifiers>
7+
<LangVersion>9</LangVersion>
8+
<Nullable>enable</Nullable>
9+
<Configurations>Debug;Release;Sideload</Configurations>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<Folder Include="StorageEnumeration\" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<Platforms>x86;x64;arm64</Platforms>
6+
<RuntimeIdentifiers>win-arm64;win-x86;win-x64</RuntimeIdentifiers>
7+
<LangVersion>9</LangVersion>
8+
<Nullable>enable</Nullable>
9+
<Configurations>Debug;Release;Sideload</Configurations>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
14+
</ItemGroup>
15+
16+
</Project>

src/Files.Sdk.Storage/IFile.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.IO;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Files.Sdk.Storage
6+
{
7+
/// <summary>
8+
/// Represents a file on the file system.
9+
/// </summary>
10+
public interface IFile : IStorable
11+
{
12+
/// <summary>
13+
/// Opens and returns a stream to the file.
14+
/// </summary>
15+
/// <param name="access">The file access to open the file with.</param>
16+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
17+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. If successful, returns a <see cref="Stream"/>, otherwise null.</returns>
18+
Task<Stream> OpenStreamAsync(FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default);
19+
}
20+
}

src/Files.Sdk.Storage/IFolder.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Files.Sdk.Storage.Enums;
5+
6+
namespace Files.Sdk.Storage
7+
{
8+
/// <summary>
9+
/// Represents a folder on the file system.
10+
/// </summary>
11+
public interface IFolder : IStorable
12+
{
13+
/// <summary>
14+
/// Gets a file in the current directory by name.
15+
/// </summary>
16+
/// <param name="fileName">The name of the file.</param>
17+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
18+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. If file is found and access is granted, returns <see cref="IFile"/> otherwise null.</returns>
19+
Task<IFile> GetFileAsync(string fileName, CancellationToken cancellationToken = default);
20+
21+
/// <summary>
22+
/// Gets a folder in the current directory by name.
23+
/// </summary>
24+
/// <param name="folderName">The name of the folder.</param>
25+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
26+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. If folder is found and access is granted, returns <see cref="IFolder"/> otherwise null.</returns>
27+
Task<IFolder> GetFolderAsync(string folderName, CancellationToken cancellationToken = default);
28+
29+
/// <summary>
30+
/// Gets all items of this directory.
31+
/// </summary>
32+
/// <param name="kind">The type of items to enumerate.</param>
33+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
34+
/// <returns>Returns an async operation represented by <see cref="IAsyncEnumerable{T}"/> of type <see cref="IStorable"/> of items in the directory.</returns>
35+
IAsyncEnumerable<IStorable> GetItemsAsync(StorableKind kind = StorableKind.All, CancellationToken cancellationToken = default);
36+
}
37+
}

src/Files.Sdk.Storage/IStorable.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Files.Sdk.Storage
2+
{
3+
/// <summary>
4+
/// Represents a base storage object on the file system.
5+
/// </summary>
6+
public interface IStorable
7+
{
8+
/// <summary>
9+
/// Gets the unique and consistent identifier for this file or folder.
10+
/// </summary>
11+
public string Id { get; }
12+
13+
/// <summary>
14+
/// Gets the name of the storage object.
15+
/// </summary>
16+
string Name { get; }
17+
}
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Files.Sdk.Storage.LocatableStorage
2+
{
3+
/// <summary>
4+
/// Represents a file that resides within a folder structure.
5+
/// </summary>
6+
public interface ILocatableFile : IFile, ILocatableStorable
7+
{
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Files.Sdk.Storage.LocatableStorage
2+
{
3+
/// <summary>
4+
/// Represents a folder that resides within a folder structure.
5+
/// </summary>
6+
public interface ILocatableFolder : IFolder, ILocatableStorable
7+
{
8+
}
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace Files.Sdk.Storage.LocatableStorage
5+
{
6+
/// <summary>
7+
/// Represents a file or folder that resides within a folder structure.
8+
/// </summary>
9+
public interface ILocatableStorable : IStorable
10+
{
11+
/// <summary>
12+
/// Gets the path where the item resides.
13+
/// </summary>
14+
string Path { get; }
15+
16+
/// <summary>
17+
/// Gets the containing folder for this item, if any.
18+
/// </summary>
19+
Task<ILocatableFolder?> GetParentAsync(CancellationToken cancellationToken = default);
20+
}
21+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Files.Sdk.Storage.ModifiableStorage
2+
{
3+
/// <summary>
4+
/// Represents a file that can be modified.
5+
/// </summary>
6+
public interface IModifiableFile : IFile, IModifiableStorable
7+
{
8+
}
9+
}

0 commit comments

Comments
 (0)