-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Feature: Added file tags widget #10477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
953404c
Initial changes
d2dyno1 99ef5c8
Initial architecture
d2dyno1 58e5644
Fixed conflicts
d2dyno1 82aaa00
Added IColorModel
d2dyno1 5e17989
Merge remote-tracking branch 'upstream/main' into f_bndlsv2
d2dyno1 7094fe0
Implemented IFileTagsService
d2dyno1 93004f1
More work on the UI
d2dyno1 fcc9db7
Storage revision
d2dyno1 8d54066
Clearer docs for IFileTagsService
d2dyno1 f903e30
Updated to main
d2dyno1 0d064b5
Revert Files.App.csproj
d2dyno1 b90af07
Revert Files.App.csproj
d2dyno1 fba0a83
Display empty UI for File Tags widget
d2dyno1 f013115
Added docs
d2dyno1 c5d6919
Fixed conflicts
d2dyno1 fc8da52
Fixed conflicts
d2dyno1 483cd76
Fixed build
d2dyno1 cdd0f98
More work on File Tags Widget
d2dyno1 f2cbafa
Changed spacing to tabs
d2dyno1 3cb022d
Nice UI updates
d2dyno1 5b55ad6
Nice UI updates 2
d2dyno1 0ccc9e3
Fixed conflicts
d2dyno1 af3e9ad
Update FileTagsSettingsService.cs
yaira2 62d9fb6
Added the option to open items
d2dyno1 a6931aa
Merge branch 'f_bndlsv2' of https://github.com/files-community/Files …
d2dyno1 e27870d
Implemented "View more" option
d2dyno1 bfb79a4
String
yaira2 887ef76
Strings
yaira2 1c2f21c
Cleanup
yaira2 e7c4045
Removed old brush converter
d2dyno1 313bbdd
Merge branch 'f_bndlsv2' of https://github.com/files-community/Files …
d2dyno1 aeecd56
Merge branch 'main' into f_bndlsv2
d2dyno1 ccf900e
Merge branch 'main' into f_bndlsv2
QuaintMako e07d6fb
Merge branch 'main' into f_bndlsv2
yaira2 f0d4974
Merge branch 'main' into f_bndlsv2
yaira2 3fcce5a
Merge branch 'main' into f_bndlsv2
yaira2 3b5e955
Fixed conflicts
d2dyno1 9e9e3fe
Merge branch 'f_bndlsv2' of https://github.com/files-community/Files …
d2dyno1 49fcbbb
Apply changes from code review
d2dyno1 ab4a805
Apply changes from code review 2
d2dyno1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using Files.Sdk.Storage; | ||
using Files.Sdk.Storage.ExtendableStorage; | ||
using Files.Sdk.Storage.LocatableStorage; | ||
using Files.Sdk.Storage.ModifiableStorage; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Files.App.Storage.NativeStorage | ||
{ | ||
/// <inheritdoc cref="IFile"/> | ||
public sealed class NativeFile : NativeStorable, ILocatableFile, IModifiableFile, IFileExtended | ||
{ | ||
public NativeFile(string path) | ||
: base(path) | ||
{ | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<Stream> OpenStreamAsync(FileAccess access, CancellationToken cancellationToken = default) | ||
{ | ||
return OpenStreamAsync(access, FileShare.None, cancellationToken); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<Stream> OpenStreamAsync(FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default) | ||
{ | ||
var stream = File.Open(Path, FileMode.Open, access, share); | ||
return Task.FromResult<Stream>(stream); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
using Files.Sdk.Storage; | ||
using Files.Sdk.Storage.Enums; | ||
using Files.Sdk.Storage.Extensions; | ||
using Files.Sdk.Storage.LocatableStorage; | ||
using Files.Sdk.Storage.ModifiableStorage; | ||
using Files.Sdk.Storage.MutableStorage; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Files.App.Storage.NativeStorage | ||
{ | ||
/// <inheritdoc cref="IFolder"/> | ||
public sealed class NativeFolder : NativeStorable, ILocatableFolder, IModifiableFolder, IMutableFolder | ||
{ | ||
public NativeFolder(string path) | ||
: base(path) | ||
{ | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<IFile> GetFileAsync(string fileName, CancellationToken cancellationToken = default) | ||
{ | ||
var path = System.IO.Path.Combine(Path, fileName); | ||
|
||
if (!File.Exists(path)) | ||
throw new FileNotFoundException(); | ||
|
||
return Task.FromResult<IFile>(new NativeFile(path)); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<IFolder> GetFolderAsync(string folderName, CancellationToken cancellationToken = default) | ||
{ | ||
var path = System.IO.Path.Combine(Path, folderName); | ||
|
||
if (!Directory.Exists(path)) | ||
throw new FileNotFoundException(); | ||
|
||
return Task.FromResult<IFolder>(new NativeFolder(path)); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async IAsyncEnumerable<IStorable> GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default) | ||
{ | ||
if (kind == StorableKind.Files) | ||
{ | ||
foreach (var item in Directory.EnumerateFiles(Path)) | ||
yield return new NativeFile(item); | ||
} | ||
else if (kind == StorableKind.Folders) | ||
{ | ||
foreach (var item in Directory.EnumerateDirectories(Path)) | ||
yield return new NativeFolder(item); | ||
} | ||
else | ||
{ | ||
foreach (var item in Directory.EnumerateFileSystemEntries(Path)) | ||
{ | ||
if (File.Exists(item)) | ||
yield return new NativeFile(item); | ||
else | ||
yield return new NativeFolder(item); | ||
} | ||
} | ||
|
||
await Task.CompletedTask; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task DeleteAsync(IStorable item, bool permanently = false, CancellationToken cancellationToken = default) | ||
{ | ||
_ = permanently; | ||
QuaintMako marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if (item is ILocatableFile locatableFile) | ||
{ | ||
File.Delete(locatableFile.Path); | ||
} | ||
else if (item is ILocatableFolder locatableFolder) | ||
{ | ||
Directory.Delete(locatableFolder.Path, true); | ||
} | ||
else | ||
throw new ArgumentException($"Could not delete {item}."); | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task<IStorable> CreateCopyOfAsync(IStorable itemToCopy, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default) | ||
{ | ||
var overwrite = collisionOption == CreationCollisionOption.ReplaceExisting; | ||
|
||
if (itemToCopy is IFile sourceFile) | ||
{ | ||
if (itemToCopy is ILocatableFile sourceLocatableFile) | ||
{ | ||
var newPath = System.IO.Path.Combine(Path, itemToCopy.Name); | ||
QuaintMako marked this conversation as resolved.
Show resolved
Hide resolved
|
||
File.Copy(sourceLocatableFile.Path, newPath, overwrite); | ||
|
||
return new NativeFile(newPath); | ||
} | ||
|
||
var copiedFile = await CreateFileAsync(itemToCopy.Name, collisionOption, cancellationToken); | ||
await sourceFile.CopyContentsToAsync(copiedFile, cancellationToken); | ||
|
||
return copiedFile; | ||
} | ||
else if (itemToCopy is IFolder sourceFolder) | ||
{ | ||
// TODO: Implement folder copy | ||
throw new NotSupportedException(); | ||
} | ||
|
||
throw new ArgumentException($"Could not copy type {itemToCopy.GetType()}"); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task<IStorable> MoveFromAsync(IStorable itemToMove, IModifiableFolder source, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default) | ||
{ | ||
var overwrite = collisionOption == CreationCollisionOption.ReplaceExisting; | ||
|
||
if (itemToMove is IFile sourceFile) | ||
{ | ||
if (itemToMove is ILocatableFile sourceLocatableFile) | ||
{ | ||
var newPath = System.IO.Path.Combine(Path, itemToMove.Name); | ||
File.Move(sourceLocatableFile.Path, newPath, overwrite); | ||
|
||
return new NativeFile(newPath); | ||
} | ||
|
||
var copiedFile = await CreateFileAsync(itemToMove.Name, collisionOption, cancellationToken); | ||
await sourceFile.CopyContentsToAsync(copiedFile, cancellationToken); | ||
await source.DeleteAsync(itemToMove, true, cancellationToken); | ||
|
||
return copiedFile; | ||
} | ||
else if (itemToMove is IFolder sourceFolder) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
throw new ArgumentException($"Could not move type {itemToMove.GetType()}"); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async Task<IFile> CreateFileAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default) | ||
{ | ||
var path = System.IO.Path.Combine(Path, desiredName); | ||
if (File.Exists(path)) | ||
{ | ||
switch (collisionOption) | ||
{ | ||
case CreationCollisionOption.GenerateUniqueName: | ||
return await CreateFileAsync($"{System.IO.Path.GetFileNameWithoutExtension(desiredName)} (1){System.IO.Path.GetExtension(desiredName)}", collisionOption, cancellationToken); | ||
|
||
case CreationCollisionOption.OpenIfExists: | ||
return new NativeFile(path); | ||
|
||
case CreationCollisionOption.FailIfExists: | ||
throw new IOException("File already exists with the same name."); | ||
} | ||
} | ||
|
||
await File.Create(path).DisposeAsync(); | ||
return new NativeFile(path); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<IFolder> CreateFolderAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default) | ||
{ | ||
var path = System.IO.Path.Combine(Path, desiredName); | ||
if (Directory.Exists(path)) | ||
{ | ||
switch (collisionOption) | ||
{ | ||
case CreationCollisionOption.GenerateUniqueName: | ||
return CreateFolderAsync($"{desiredName} (1)", collisionOption, cancellationToken); | ||
|
||
case CreationCollisionOption.OpenIfExists: | ||
return Task.FromResult<IFolder>(new NativeFolder(path)); | ||
|
||
case CreationCollisionOption.FailIfExists: | ||
throw new IOException("Folder already exists with the same name."); | ||
} | ||
} | ||
|
||
_ = Directory.CreateDirectory(path); | ||
return Task.FromResult<IFolder>(new NativeFolder(path)); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public Task<IFolderWatcher> GetFolderWatcherAsync(CancellationToken cancellationToken = default) | ||
{ | ||
return Task.FromResult<IFolderWatcher>(new NativeFolderWatcher(this)); | ||
} | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
src/Files.App.Storage/NativeStorage/NativeFolderWatcher.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
using Files.Sdk.Storage.LocatableStorage; | ||
using Files.Sdk.Storage.MutableStorage; | ||
using System.Collections.Specialized; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
|
||
namespace Files.App.Storage.NativeStorage | ||
{ | ||
/// <inheritdoc cref="IFolderWatcher"/> | ||
public sealed class NativeFolderWatcher : IFolderWatcher | ||
{ | ||
private FileSystemWatcher? _fileSystemWatcher; | ||
private NotifyCollectionChangedEventHandler? _collectionChanged; | ||
QuaintMako marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public IMutableFolder Folder { get; } | ||
|
||
/// <inheritdoc/> | ||
public event NotifyCollectionChangedEventHandler? CollectionChanged | ||
{ | ||
add | ||
{ | ||
if (_fileSystemWatcher is not null) | ||
_fileSystemWatcher.EnableRaisingEvents = true; | ||
|
||
_collectionChanged += value; | ||
} | ||
remove | ||
{ | ||
if (_fileSystemWatcher is not null) | ||
_fileSystemWatcher.EnableRaisingEvents = false; | ||
|
||
_collectionChanged -= value; | ||
} | ||
} | ||
|
||
public NativeFolderWatcher(IMutableFolder folder) | ||
{ | ||
Folder = folder; | ||
SetupWatcher(); | ||
} | ||
|
||
private void SetupWatcher() | ||
{ | ||
if (Folder is ILocatableFolder locatableFolder) | ||
{ | ||
_fileSystemWatcher = new(locatableFolder.Path); | ||
_fileSystemWatcher.Created += FileSystemWatcher_Created; | ||
_fileSystemWatcher.Deleted += FileSystemWatcher_Deleted; | ||
_fileSystemWatcher.Renamed += FileSystemWatcher_Renamed; | ||
} | ||
} | ||
|
||
private void FileSystemWatcher_Renamed(object sender, RenamedEventArgs e) | ||
{ | ||
_collectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Replace, e.FullPath, e.OldFullPath)); | ||
} | ||
|
||
private void FileSystemWatcher_Deleted(object sender, FileSystemEventArgs e) | ||
{ | ||
_collectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Remove, e.FullPath)); | ||
} | ||
|
||
private void FileSystemWatcher_Created(object sender, FileSystemEventArgs e) | ||
{ | ||
_collectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Add, e.FullPath)); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public ValueTask DisposeAsync() | ||
{ | ||
Dispose(); | ||
return default; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void Dispose() | ||
{ | ||
if (_fileSystemWatcher is not null) | ||
{ | ||
_fileSystemWatcher.EnableRaisingEvents = false; | ||
_fileSystemWatcher.Created -= FileSystemWatcher_Created; | ||
_fileSystemWatcher.Deleted -= FileSystemWatcher_Deleted; | ||
_fileSystemWatcher.Renamed -= FileSystemWatcher_Renamed; | ||
_fileSystemWatcher.Dispose(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.