diff --git a/src/Files.App.Storage/FtpStorage/FtpStorable.cs b/src/Files.App.Storage/FtpStorage/FtpStorable.cs
index 8fdb51c2180f..75ec533953c9 100644
--- a/src/Files.App.Storage/FtpStorage/FtpStorable.cs
+++ b/src/Files.App.Storage/FtpStorage/FtpStorable.cs
@@ -1,37 +1,43 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
+using Files.Core.Storage;
using Files.Core.Storage.LocatableStorage;
-using Files.Shared.Helpers;
+using Files.Core.Storage.NestedStorage;
using FluentFTP;
using System.Threading;
using System.Threading.Tasks;
namespace Files.App.Storage.FtpStorage
{
- public abstract class FtpStorable : ILocatableStorable
+ public abstract class FtpStorable : ILocatableStorable, INestedStorable
{
- private string? _computedId;
-
///
- public string Path { get; protected set; }
+ public virtual string Path { get; protected set; }
///
- public string Name { get; protected set; }
+ public virtual string Name { get; protected set; }
///
- public virtual string Id => _computedId ??= ChecksumHelpers.CalculateChecksumForPath(Path);
+ public virtual string Id { get; }
+
+ ///
+ /// Gets the parent folder of the storable, if any.
+ ///
+ protected virtual IFolder? Parent { get; }
- protected internal FtpStorable(string path, string name)
+ protected internal FtpStorable(string path, string name, IFolder? parent)
{
Path = FtpHelpers.GetFtpPath(path);
Name = name;
+ Id = Path;
+ Parent = parent;
}
///
- public virtual Task GetParentAsync(CancellationToken cancellationToken = default)
+ public Task GetParentAsync(CancellationToken cancellationToken = default)
{
- return Task.FromResult(null);
+ return Task.FromResult(Parent);
}
protected AsyncFtpClient GetFtpClient()
diff --git a/src/Files.App.Storage/FtpStorage/FtpStorageFile.cs b/src/Files.App.Storage/FtpStorage/FtpStorageFile.cs
index 19db8d6ffa98..55ed99f60083 100644
--- a/src/Files.App.Storage/FtpStorage/FtpStorageFile.cs
+++ b/src/Files.App.Storage/FtpStorage/FtpStorageFile.cs
@@ -1,8 +1,10 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
+using Files.Core.Storage;
using Files.Core.Storage.LocatableStorage;
using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
using System;
using System.IO;
using System.Threading;
@@ -10,10 +12,10 @@
namespace Files.App.Storage.FtpStorage
{
- public sealed class FtpStorageFile : FtpStorable, IModifiableFile, ILocatableFile
+ public sealed class FtpStorageFile : FtpStorable, IModifiableFile, ILocatableFile, INestedFile
{
- public FtpStorageFile(string path, string name)
- : base(path, name)
+ public FtpStorageFile(string path, string name, IFolder? parent)
+ : base(path, name, parent)
{
}
@@ -24,17 +26,11 @@ public async Task OpenStreamAsync(FileAccess access, CancellationToken c
await ftpClient.EnsureConnectedAsync(cancellationToken);
if (access.HasFlag(FileAccess.Write))
- {
return await ftpClient.OpenWrite(Path, token: cancellationToken);
- }
else if (access.HasFlag(FileAccess.Read))
- {
return await ftpClient.OpenRead(Path, token: cancellationToken);
- }
else
- {
throw new ArgumentException($"Invalid {nameof(access)} flag.");
- }
}
}
}
diff --git a/src/Files.App.Storage/FtpStorage/FtpStorageFolder.cs b/src/Files.App.Storage/FtpStorage/FtpStorageFolder.cs
index 3fa1e49902d3..448251578250 100644
--- a/src/Files.App.Storage/FtpStorage/FtpStorageFolder.cs
+++ b/src/Files.App.Storage/FtpStorage/FtpStorageFolder.cs
@@ -2,10 +2,13 @@
// Licensed under the MIT License. See the LICENSE.
using Files.Core.Storage;
+using Files.Core.Storage.DirectStorage;
using Files.Core.Storage.Enums;
+using Files.Core.Storage.ExtendableStorage;
using Files.Core.Storage.Extensions;
using Files.Core.Storage.LocatableStorage;
using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
using Files.Shared.Helpers;
using FluentFTP;
using System;
@@ -17,15 +20,15 @@
namespace Files.App.Storage.FtpStorage
{
- public sealed class FtpStorageFolder : FtpStorable, ILocatableFolder, IModifiableFolder
+ public sealed class FtpStorageFolder : FtpStorable, ILocatableFolder, IModifiableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
{
- public FtpStorageFolder(string path, string name)
- : base(path, name)
+ public FtpStorageFolder(string path, string name, IFolder? parent)
+ : base(path, name, parent)
{
}
///
- public async Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
+ public async Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -36,11 +39,11 @@ public async Task GetFileAsync(string fileName, CancellationToken cancell
if (item is null || item.Type != FtpObjectType.File)
throw new FileNotFoundException();
- return new FtpStorageFile(path, item.Name);
+ return new FtpStorageFile(path, item.Name, this);
}
///
- public async Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
+ public async Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -51,11 +54,11 @@ public async Task GetFolderAsync(string folderName, CancellationToken c
if (item is null || item.Type != FtpObjectType.Directory)
throw new DirectoryNotFoundException();
- return new FtpStorageFolder(path, item.Name);
+ return new FtpStorageFolder(path, item.Name, this);
}
///
- public async IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ public async IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -65,7 +68,7 @@ public async IAsyncEnumerable GetItemsAsync(StorableKind kind = Stora
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
{
if (item.Type == FtpObjectType.File)
- yield return new FtpStorageFile(item.FullName, item.Name);
+ yield return new FtpStorageFile(item.FullName, item.Name, this);
}
}
else if (kind == StorableKind.Folders)
@@ -73,7 +76,7 @@ public async IAsyncEnumerable GetItemsAsync(StorableKind kind = Stora
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
{
if (item.Type == FtpObjectType.Directory)
- yield return new FtpStorageFolder(item.FullName, item.Name);
+ yield return new FtpStorageFolder(item.FullName, item.Name, this);
}
}
else
@@ -81,16 +84,16 @@ public async IAsyncEnumerable GetItemsAsync(StorableKind kind = Stora
foreach (var item in await ftpClient.GetListing(Path, cancellationToken))
{
if (item.Type == FtpObjectType.File)
- yield return new FtpStorageFile(item.FullName, item.Name);
+ yield return new FtpStorageFile(item.FullName, item.Name, this);
if (item.Type == FtpObjectType.Directory)
- yield return new FtpStorageFolder(item.FullName, item.Name);
+ yield return new FtpStorageFolder(item.FullName, item.Name, this);
}
}
}
///
- public async Task DeleteAsync(IStorable item, bool permanently = false, CancellationToken cancellationToken = default)
+ public async Task DeleteAsync(INestedStorable item, bool permanently = false, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
@@ -110,11 +113,11 @@ public async Task DeleteAsync(IStorable item, bool permanently = false, Cancella
}
///
- public async Task CreateCopyOfAsync(IStorable itemToCopy, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateCopyOfAsync(INestedStorable itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default)
{
if (itemToCopy is IFile sourceFile)
{
- var copiedFile = await CreateFileAsync(itemToCopy.Name, collisionOption, cancellationToken);
+ var copiedFile = await CreateFileAsync(itemToCopy.Name, overwrite, cancellationToken);
await sourceFile.CopyContentsToAsync(copiedFile, cancellationToken);
return copiedFile;
@@ -126,41 +129,34 @@ public async Task CreateCopyOfAsync(IStorable itemToCopy, CreationCol
}
///
- public async Task MoveFromAsync(IStorable itemToMove, IModifiableFolder source, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task MoveFromAsync(INestedStorable itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
- var newItem = await CreateCopyOfAsync(itemToMove, collisionOption, cancellationToken);
+ var newItem = await CreateCopyOfAsync(itemToMove, overwrite, cancellationToken);
await source.DeleteAsync(itemToMove, true, cancellationToken);
return newItem;
}
///
- public async Task CreateFileAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateFileAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
var newPath = $"{Path}/{desiredName}";
- if (await ftpClient.FileExists(newPath, cancellationToken))
- {
- if (collisionOption == CreationCollisionOption.FailIfExists)
- throw new IOException("File already exists.");
-
- if (collisionOption == CreationCollisionOption.OpenIfExists)
- return new FtpStorageFile(newPath, desiredName);
- }
+ if (overwrite && await ftpClient.FileExists(newPath, cancellationToken))
+ throw new IOException("File already exists.");
using var stream = new MemoryStream();
- var replaceExisting = collisionOption == CreationCollisionOption.ReplaceExisting;
- var result = await ftpClient.UploadStream(stream, newPath, replaceExisting ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip, token: cancellationToken);
+ var result = await ftpClient.UploadStream(stream, newPath, overwrite ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip, token: cancellationToken);
if (result == FtpStatus.Success)
{
// Success
- return new FtpStorageFile(newPath, desiredName);
+ return new FtpStorageFile(newPath, desiredName, this);
}
else if (result == FtpStatus.Skipped)
{
@@ -175,27 +171,20 @@ public async Task CreateFileAsync(string desiredName, CreationCollisionOp
}
///
- public async Task CreateFolderAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
var newPath = $"{Path}/{desiredName}";
- if (await ftpClient.DirectoryExists(newPath, cancellationToken))
- {
- if (collisionOption == CreationCollisionOption.FailIfExists)
- throw new IOException("Directory already exists.");
-
- if (collisionOption == CreationCollisionOption.OpenIfExists)
- return new FtpStorageFolder(newPath, desiredName);
- }
+ if (overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))
+ throw new IOException("Directory already exists.");
- var replaceExisting = collisionOption == CreationCollisionOption.ReplaceExisting;
- var isSuccessful = await ftpClient.CreateDirectory(newPath, replaceExisting, cancellationToken);
+ var isSuccessful = await ftpClient.CreateDirectory(newPath, overwrite, cancellationToken);
if (!isSuccessful)
throw new IOException("Directory was not successfully created.");
- return new FtpStorageFolder(newPath, desiredName);
+ return new FtpStorageFolder(newPath, desiredName, this);
}
}
}
diff --git a/src/Files.App.Storage/FtpStorage/FtpStorageService.cs b/src/Files.App.Storage/FtpStorage/FtpStorageService.cs
index 9ae28d928cce..f468fde30c81 100644
--- a/src/Files.App.Storage/FtpStorage/FtpStorageService.cs
+++ b/src/Files.App.Storage/FtpStorage/FtpStorageService.cs
@@ -4,70 +4,41 @@
using Files.Core.Storage;
using Files.Core.Storage.LocatableStorage;
using FluentFTP;
-using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Files.App.Storage.FtpStorage
{
+ ///
public sealed class FtpStorageService : IFtpStorageService
{
- public Task IsAccessibleAsync(CancellationToken cancellationToken = default)
+ ///
+ public async Task GetFolderAsync(string id, CancellationToken cancellationToken = default)
{
- return Task.FromResult(true); // TODO: Check if FTP is available
- }
-
- public async Task FileExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- try
- {
- _ = await GetFileFromPathAsync(path, cancellationToken);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- public async Task DirectoryExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- try
- {
- _ = await GetFolderFromPathAsync(path, cancellationToken);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- public async Task GetFolderFromPathAsync(string path, CancellationToken cancellationToken = default)
- {
- using var ftpClient = FtpHelpers.GetFtpClient(path);
+ using var ftpClient = FtpHelpers.GetFtpClient(id);
await ftpClient.EnsureConnectedAsync(cancellationToken);
- var ftpPath = FtpHelpers.GetFtpPath(path);
+ var ftpPath = FtpHelpers.GetFtpPath(id);
var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
if (item is null || item.Type != FtpObjectType.Directory)
throw new DirectoryNotFoundException("Directory was not found from path.");
- return new FtpStorageFolder(ftpPath, item.Name);
+ return new FtpStorageFolder(ftpPath, item.Name, null);
}
- public async Task GetFileFromPathAsync(string path, CancellationToken cancellationToken = default)
+ ///
+ public async Task GetFileAsync(string id, CancellationToken cancellationToken = default)
{
- using var ftpClient = FtpHelpers.GetFtpClient(path);
+ using var ftpClient = FtpHelpers.GetFtpClient(id);
await ftpClient.EnsureConnectedAsync(cancellationToken);
- var ftpPath = FtpHelpers.GetFtpPath(path);
+ var ftpPath = FtpHelpers.GetFtpPath(id);
var item = await ftpClient.GetObjectInfo(ftpPath, token: cancellationToken);
if (item is null || item.Type != FtpObjectType.File)
throw new FileNotFoundException("File was not found from path.");
- return new FtpStorageFile(ftpPath, item.Name);
+ return new FtpStorageFile(ftpPath, item.Name, null);
}
}
}
diff --git a/src/Files.App.Storage/NativeStorage/NativeFile.cs b/src/Files.App.Storage/NativeStorage/NativeFile.cs
index cb530030caed..a22e9b6eab57 100644
--- a/src/Files.App.Storage/NativeStorage/NativeFile.cs
+++ b/src/Files.App.Storage/NativeStorage/NativeFile.cs
@@ -5,6 +5,7 @@
using Files.Core.Storage.ExtendableStorage;
using Files.Core.Storage.LocatableStorage;
using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -12,21 +13,26 @@
namespace Files.App.Storage.NativeStorage
{
///
- public sealed class NativeFile : NativeStorable, ILocatableFile, IModifiableFile, IFileExtended
+ public class NativeFile : NativeStorable, ILocatableFile, IModifiableFile, IFileExtended, INestedFile
{
+ public NativeFile(FileInfo fileInfo)
+ : base(fileInfo)
+ {
+ }
+
public NativeFile(string path)
- : base(path)
+ : this(new FileInfo(path))
{
}
///
- public Task OpenStreamAsync(FileAccess access, CancellationToken cancellationToken = default)
+ public virtual Task OpenStreamAsync(FileAccess access, CancellationToken cancellationToken = default)
{
return OpenStreamAsync(access, FileShare.None, cancellationToken);
}
///
- public Task OpenStreamAsync(FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default)
+ public virtual Task OpenStreamAsync(FileAccess access, FileShare share = FileShare.None, CancellationToken cancellationToken = default)
{
var stream = File.Open(Path, FileMode.Open, access, share);
return Task.FromResult(stream);
diff --git a/src/Files.App.Storage/NativeStorage/NativeFolder.cs b/src/Files.App.Storage/NativeStorage/NativeFolder.cs
index 834d45529b35..fedea9a05bfb 100644
--- a/src/Files.App.Storage/NativeStorage/NativeFolder.cs
+++ b/src/Files.App.Storage/NativeStorage/NativeFolder.cs
@@ -2,11 +2,14 @@
// Licensed under the MIT License. See the LICENSE.
using Files.Core.Storage;
+using Files.Core.Storage.DirectStorage;
using Files.Core.Storage.Enums;
+using Files.Core.Storage.ExtendableStorage;
using Files.Core.Storage.Extensions;
using Files.Core.Storage.LocatableStorage;
using Files.Core.Storage.ModifiableStorage;
using Files.Core.Storage.MutableStorage;
+using Files.Core.Storage.NestedStorage;
using System;
using System.Collections.Generic;
using System.IO;
@@ -16,65 +19,69 @@
namespace Files.App.Storage.NativeStorage
{
- ///
- public sealed class NativeFolder : NativeStorable, ILocatableFolder, IModifiableFolder, IMutableFolder
+ ///
+ public class NativeFolder : NativeStorable, ILocatableFolder, IModifiableFolder, IMutableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
{
- public NativeFolder(string path)
- : base(path)
- {
- }
-
- ///
- public Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
- {
- var path = System.IO.Path.Combine(Path, fileName);
-
- if (!File.Exists(path))
- throw new FileNotFoundException();
-
- return Task.FromResult(new NativeFile(path));
- }
-
- ///
- public Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
- {
- var path = System.IO.Path.Combine(Path, folderName);
-
- if (!Directory.Exists(path))
- throw new FileNotFoundException();
-
- return Task.FromResult(new NativeFolder(path));
- }
-
- ///
- public async IAsyncEnumerable 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;
- }
-
- ///
- public Task DeleteAsync(IStorable item, bool permanently = false, CancellationToken cancellationToken = default)
+ public NativeFolder(DirectoryInfo directoryInfo)
+ : base(directoryInfo)
+ {
+ }
+
+ public NativeFolder(string path)
+ : this(new DirectoryInfo(path))
+ {
+ }
+
+ ///
+ public virtual Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
+ {
+ var path = System.IO.Path.Combine(Path, fileName);
+
+ if (!File.Exists(path))
+ throw new FileNotFoundException();
+
+ return Task.FromResult(new NativeFile(path));
+ }
+
+ ///
+ public virtual Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
+ {
+ var path = System.IO.Path.Combine(Path, folderName);
+ if (!Directory.Exists(path))
+ throw new FileNotFoundException();
+
+ return Task.FromResult(new NativeFolder(path));
+ }
+
+ ///
+ public virtual async IAsyncEnumerable 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;
+ }
+
+ ///
+ public virtual Task DeleteAsync(INestedStorable item, bool permanently = false, CancellationToken cancellationToken = default)
{
_ = permanently;
@@ -92,112 +99,86 @@ public Task DeleteAsync(IStorable item, bool permanently = false, CancellationTo
return Task.CompletedTask;
}
- ///
- public async Task 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);
- 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()}");
- }
-
- ///
- public async Task 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()}");
- }
-
- ///
- public async Task 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);
- }
-
- ///
- public Task 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(new NativeFolder(path));
-
- case CreationCollisionOption.FailIfExists:
- throw new IOException("Folder already exists with the same name.");
- }
- }
-
- _ = Directory.CreateDirectory(path);
- return Task.FromResult(new NativeFolder(path));
- }
-
- ///
- public Task GetFolderWatcherAsync(CancellationToken cancellationToken = default)
+ ///
+ public virtual async Task CreateCopyOfAsync(INestedStorable itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default)
+ {
+ if (itemToCopy is IFile sourceFile)
+ {
+ if (itemToCopy is ILocatableFile sourceLocatableFile)
+ {
+ var newPath = System.IO.Path.Combine(Path, itemToCopy.Name);
+ File.Copy(sourceLocatableFile.Path, newPath, overwrite);
+
+ return new NativeFile(newPath);
+ }
+
+ var copiedFile = await CreateFileAsync(itemToCopy.Name, overwrite, cancellationToken);
+ await sourceFile.CopyContentsToAsync(copiedFile, cancellationToken);
+
+ return copiedFile;
+ }
+ else if (itemToCopy is IFolder sourceFolder)
+ {
+ // TODO: Implement folder copy
+ _ = sourceFolder;
+ throw new NotSupportedException();
+ }
+
+ throw new ArgumentException($"Could not copy type {itemToCopy.GetType()}");
+ }
+
+ ///
+ public virtual async Task MoveFromAsync(INestedStorable itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default)
+ {
+ 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);
+ }
+ else
+ {
+ var copiedFile = await CreateFileAsync(itemToMove.Name, overwrite, 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()}");
+ }
+
+ ///
+ public virtual async Task CreateFileAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
+ {
+ var path = System.IO.Path.Combine(Path, desiredName);
+ if (overwrite || !File.Exists(path))
+ await File.Create(path).DisposeAsync();
+
+ return new NativeFile(path);
+ }
+
+ ///
+ public virtual Task CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
+ {
+ var path = System.IO.Path.Combine(Path, desiredName);
+ if (overwrite)
+ Directory.Delete(path, true);
+
+ _ = Directory.CreateDirectory(path);
+ return Task.FromResult(new NativeFolder(path));
+ }
+
+ ///
+ public Task GetFolderWatcherAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(new NativeFolderWatcher(this));
}
diff --git a/src/Files.App.Storage/NativeStorage/NativeStorable.cs b/src/Files.App.Storage/NativeStorage/NativeStorable.cs
index 9d36ce8c3e3e..1a8fbcc3ca7a 100644
--- a/src/Files.App.Storage/NativeStorage/NativeStorable.cs
+++ b/src/Files.App.Storage/NativeStorage/NativeStorable.cs
@@ -3,40 +3,62 @@
using Files.Core.Storage;
using Files.Core.Storage.LocatableStorage;
-using Files.Shared.Helpers;
+using Files.Core.Storage.NestedStorage;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Files.App.Storage.NativeStorage
{
///
- public abstract class NativeStorable : ILocatableStorable
+ public abstract class NativeStorable : ILocatableStorable, INestedStorable
+ where TStorage : FileSystemInfo
{
- private string? _computedId;
+ protected readonly TStorage storage;
///
- public string Path { get; protected set; }
+ public virtual string Path { get; protected set; }
///
- public string Name { get; protected set; }
+ public virtual string Name { get; protected set; }
///
- public virtual string Id => _computedId ??= ChecksumHelpers.CalculateChecksumForPath(Path);
+ public virtual string Id { get; }
- protected NativeStorable(string path)
+ protected NativeStorable(TStorage storage)
{
- Path = path;
- Name = System.IO.Path.GetFileName(path);
+ this.storage = storage;
+ Path = storage.FullName;
+ Name = storage.Name;
+ Id = storage.FullName;
}
///
- public virtual Task GetParentAsync(CancellationToken cancellationToken = default)
+ public virtual Task GetParentAsync(CancellationToken cancellationToken = default)
{
- var parentPath = System.IO.Path.GetDirectoryName(Path);
- if (string.IsNullOrEmpty(parentPath))
- return Task.FromResult(null);
+ var parent = Directory.GetParent(Path);
+ if (parent is null)
+ return Task.FromResult(null);
- return Task.FromResult(new NativeFolder(parentPath));
+ return Task.FromResult(new NativeFolder(parent));
+ }
+
+ ///
+ /// Formats a given .
+ ///
+ /// The path to format.
+ /// A formatted path.
+ protected static string FormatPath(string path)
+ {
+ path = path.Replace("file:///", string.Empty);
+
+ if ('/' != System.IO.Path.DirectorySeparatorChar)
+ return path.Replace('/', System.IO.Path.DirectorySeparatorChar);
+
+ if ('\\' != System.IO.Path.DirectorySeparatorChar)
+ return path.Replace('\\', System.IO.Path.DirectorySeparatorChar);
+
+ return path;
}
}
}
diff --git a/src/Files.App.Storage/NativeStorage/NativeStorageService.cs b/src/Files.App.Storage/NativeStorage/NativeStorageService.cs
index 3b206414b28a..7e2326325dce 100644
--- a/src/Files.App.Storage/NativeStorage/NativeStorageService.cs
+++ b/src/Files.App.Storage/NativeStorage/NativeStorageService.cs
@@ -13,41 +13,21 @@ namespace Files.App.Storage.NativeStorage
public sealed class NativeStorageService : IStorageService
{
///
- public Task IsAccessibleAsync(CancellationToken cancellationToken = default)
+ public Task GetFileAsync(string id, CancellationToken cancellationToken = default)
{
- return Task.FromResult(true);
- }
-
- ///
- public Task FileExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- var fileExists = File.Exists(path);
- return Task.FromResult(fileExists);
- }
-
- ///
- public Task DirectoryExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- var directoryExists = Directory.Exists(path);
- return Task.FromResult(directoryExists);
- }
-
- ///
- public Task GetFolderFromPathAsync(string path, CancellationToken cancellationToken = default)
- {
- if (!Directory.Exists(path))
- throw new DirectoryNotFoundException($"Directory for '{path}' was not found.");
+ if (!File.Exists(id))
+ throw new FileNotFoundException();
- return Task.FromResult(new NativeFolder(path));
+ return Task.FromResult(new NativeFile(id));
}
///
- public Task GetFileFromPathAsync(string path, CancellationToken cancellationToken = default)
+ public Task GetFolderAsync(string id, CancellationToken cancellationToken = default)
{
- if (!File.Exists(path))
- throw new FileNotFoundException($"File for '{path}' was not found.");
+ if (!Directory.Exists(id))
+ throw new DirectoryNotFoundException();
- return Task.FromResult(new NativeFile(path));
+ return Task.FromResult(new NativeFolder(id));
}
}
}
diff --git a/src/Files.App.Storage/WindowsStorage/WindowsStorable.cs b/src/Files.App.Storage/WindowsStorage/WindowsStorable.cs
index d6309af73e4a..64a60577746b 100644
--- a/src/Files.App.Storage/WindowsStorage/WindowsStorable.cs
+++ b/src/Files.App.Storage/WindowsStorage/WindowsStorable.cs
@@ -3,6 +3,7 @@
using Files.Core.Storage;
using Files.Core.Storage.LocatableStorage;
+using Files.Core.Storage.NestedStorage;
using Files.Shared.Helpers;
using System.Threading;
using System.Threading.Tasks;
@@ -11,7 +12,7 @@
namespace Files.App.Storage.WindowsStorage
{
///
- public abstract class WindowsStorable : ILocatableStorable
+ public abstract class WindowsStorable : ILocatableStorable, INestedStorable
where TStorage : class, IStorageItem
{
private string? _computedId;
@@ -34,6 +35,6 @@ protected internal WindowsStorable(TStorage storage)
}
///
- public abstract Task GetParentAsync(CancellationToken cancellationToken = default);
+ public abstract Task GetParentAsync(CancellationToken cancellationToken = default);
}
}
diff --git a/src/Files.App.Storage/WindowsStorage/WindowsStorageFile.cs b/src/Files.App.Storage/WindowsStorage/WindowsStorageFile.cs
index d821965be987..a4ed6be48fbd 100644
--- a/src/Files.App.Storage/WindowsStorage/WindowsStorageFile.cs
+++ b/src/Files.App.Storage/WindowsStorage/WindowsStorageFile.cs
@@ -5,6 +5,7 @@
using Files.Core.Storage.ExtendableStorage;
using Files.Core.Storage.LocatableStorage;
using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
using System;
using System.IO;
using System.Threading;
@@ -14,7 +15,7 @@
namespace Files.App.Storage.WindowsStorage
{
///
- public sealed class WindowsStorageFile : WindowsStorable, ILocatableFile, IModifiableFile, IFileExtended
+ public sealed class WindowsStorageFile : WindowsStorable, ILocatableFile, IModifiableFile, IFileExtended, INestedFile
{
public WindowsStorageFile(StorageFile storage)
: base(storage)
@@ -40,7 +41,7 @@ public async Task OpenStreamAsync(FileAccess access, FileShare share = F
}
///
- public override async Task GetParentAsync(CancellationToken cancellationToken = default)
+ public override async Task GetParentAsync(CancellationToken cancellationToken = default)
{
var parentFolderTask = storage.GetParentAsync().AsTask(cancellationToken);
var parentFolder = await parentFolderTask;
diff --git a/src/Files.App.Storage/WindowsStorage/WindowsStorageFolder.cs b/src/Files.App.Storage/WindowsStorage/WindowsStorageFolder.cs
index bb0befc45298..9f217b79b0ad 100644
--- a/src/Files.App.Storage/WindowsStorage/WindowsStorageFolder.cs
+++ b/src/Files.App.Storage/WindowsStorage/WindowsStorageFolder.cs
@@ -11,94 +11,106 @@
using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;
-using CreationCollisionOption = Files.Core.Storage.Enums.CreationCollisionOption;
+using Files.Core.Storage.DirectStorage;
+using Files.Core.Storage.ExtendableStorage;
+using Files.Core.Storage.NestedStorage;
namespace Files.App.Storage.WindowsStorage
{
///
- public sealed class WindowsStorageFolder : WindowsStorable, ILocatableFolder, IModifiableFolder
+ public sealed class WindowsStorageFolder : WindowsStorable, ILocatableFolder, IFolderExtended, INestedFolder, IDirectCopy, IDirectMove
{
+ // TODO: Implement IMutableFolder
+
public WindowsStorageFolder(StorageFolder storage)
: base(storage)
{
}
///
- public async Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
+ public async Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
{
- var fileTask = storage.GetFileAsync(fileName).AsTask(cancellationToken);
- var file = await fileTask;
-
+ var file = await storage.GetFileAsync(fileName).AsTask(cancellationToken);
return new WindowsStorageFile(file);
}
///
- public async Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
+ public async Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
{
- var folderTask = storage.GetFolderAsync(folderName).AsTask(cancellationToken);
- var folder = await folderTask;
-
+ var folder = await storage.GetFolderAsync(folderName).AsTask(cancellationToken);
return new WindowsStorageFolder(folder);
}
///
- public async IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ public async IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
- if (kind == StorableKind.Files)
+ switch (kind)
{
- var files = await storage.GetFilesAsync().AsTask(cancellationToken);
- foreach (var item in files)
+ case StorableKind.Files:
{
- yield return new WindowsStorageFile(item);
+ var files = await storage.GetFilesAsync().AsTask(cancellationToken);
+ foreach (var item in files)
+ {
+ yield return new WindowsStorageFile(item);
+ }
+
+ break;
}
- }
- else if (kind == StorableKind.Folders)
- {
- var folders = await storage.GetFoldersAsync().AsTask(cancellationToken);
- foreach (var item in folders)
+
+ case StorableKind.Folders:
{
- yield return new WindowsStorageFolder(item);
+ var folders = await storage.GetFoldersAsync().AsTask(cancellationToken);
+ foreach (var item in folders)
+ {
+ yield return new WindowsStorageFolder(item);
+ }
+
+ break;
}
- }
- else
- {
- var items = await storage.GetItemsAsync().AsTask(cancellationToken);
- foreach (var item in items)
+
+ case StorableKind.All:
{
- if (item is StorageFile storageFile)
- yield return new WindowsStorageFile(storageFile);
+ var items = await storage.GetItemsAsync().AsTask(cancellationToken);
+ foreach (var item in items)
+ {
+ if (item is StorageFile storageFile)
+ yield return new WindowsStorageFile(storageFile);
+
+ if (item is StorageFolder storageFolder)
+ yield return new WindowsStorageFolder(storageFolder);
+ }
- if (item is StorageFolder storageFolder)
- yield return new WindowsStorageFolder(storageFolder);
+ break;
}
+
+ default:
+ yield break;
}
}
///
- public async Task DeleteAsync(IStorable item, bool permanently = false, CancellationToken cancellationToken = default)
+ public Task DeleteAsync(INestedStorable item, bool permanently = default, CancellationToken cancellationToken = default)
{
- if (item is WindowsStorable storageFile)
- {
- await storageFile.storage.DeleteAsync(GetWindowsStorageDeleteOption(permanently)).AsTask(cancellationToken);
- }
- else if (item is WindowsStorable storageFolder)
+ return item switch
{
- await storageFolder.storage.DeleteAsync(GetWindowsStorageDeleteOption(permanently)).AsTask(cancellationToken);
- }
- else
- {
- throw new NotImplementedException();
- }
+ WindowsStorable storageFile => storageFile.storage
+ .DeleteAsync(GetWindowsStorageDeleteOption(permanently))
+ .AsTask(cancellationToken),
+
+ WindowsStorable storageFolder => storageFolder.storage
+ .DeleteAsync(GetWindowsStorageDeleteOption(permanently))
+ .AsTask(cancellationToken),
+
+ _ => throw new NotImplementedException()
+ };
}
///
- public async Task CreateCopyOfAsync(IStorable itemToCopy, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateCopyOfAsync(INestedStorable itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default)
{
- if (itemToCopy is WindowsStorable storageFile)
+ if (itemToCopy is WindowsStorable sourceFile)
{
- var copiedFileTask = storageFile.storage.CopyAsync(storage, itemToCopy.Name, GetWindowsNameCollisionOption(collisionOption)).AsTask(cancellationToken);
- var copiedFile = await copiedFileTask;
-
+ var copiedFile = await sourceFile.storage.CopyAsync(storage, itemToCopy.Name, GetWindowsNameCollisionOption(overwrite)).AsTask(cancellationToken);
return new WindowsStorageFile(copiedFile);
}
@@ -106,72 +118,51 @@ public async Task CreateCopyOfAsync(IStorable itemToCopy, CreationCol
}
///
- public async Task MoveFromAsync(IStorable itemToMove, IModifiableFolder source, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task MoveFromAsync(INestedStorable itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default)
{
- if (itemToMove is WindowsStorable storageFile)
+ if (itemToMove is WindowsStorable sourceFile)
{
- await storageFile.storage.MoveAsync(storage, itemToMove.Name, GetWindowsNameCollisionOption(collisionOption)).AsTask(cancellationToken);
- return new WindowsStorageFile(storageFile.storage);
+ await sourceFile.storage.MoveAsync(storage, itemToMove.Name, GetWindowsNameCollisionOption(overwrite)).AsTask(cancellationToken);
+ return new WindowsStorageFile(sourceFile.storage);
}
throw new ArgumentException($"Could not copy type {itemToMove.GetType()}");
}
///
- public async Task CreateFileAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateFileAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
{
- var fileTask = storage.CreateFileAsync(desiredName, GetWindowsCreationCollisionOption(collisionOption)).AsTask(cancellationToken);
- var file = await fileTask;
-
+ var file = await storage.CreateFileAsync(desiredName, GetWindowsCreationCollisionOption(overwrite)).AsTask(cancellationToken);
return new WindowsStorageFile(file);
}
///
- public async Task CreateFolderAsync(string desiredName, CreationCollisionOption collisionOption = default, CancellationToken cancellationToken = default)
+ public async Task CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
{
- var folderTask = storage.CreateFolderAsync(desiredName, GetWindowsCreationCollisionOption(collisionOption)).AsTask(cancellationToken);
- var folder = await folderTask;
-
+ var folder = await storage.CreateFolderAsync(desiredName, GetWindowsCreationCollisionOption(overwrite)).AsTask(cancellationToken);
return new WindowsStorageFolder(folder);
}
///
- public override async Task GetParentAsync(CancellationToken cancellationToken = default)
+ public override async Task GetParentAsync(CancellationToken cancellationToken = default)
{
- var parentFolderTask = storage.GetParentAsync().AsTask(cancellationToken);
- var parentFolder = await parentFolderTask;
-
+ var parentFolder = await storage.GetParentAsync().AsTask(cancellationToken);
return new WindowsStorageFolder(parentFolder);
}
- private static StorageDeleteOption GetWindowsStorageDeleteOption(bool deletePermanentlyFlag)
+ private static StorageDeleteOption GetWindowsStorageDeleteOption(bool permanently)
{
- return deletePermanentlyFlag ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default;
+ return permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default;
}
- private static Windows.Storage.NameCollisionOption GetWindowsNameCollisionOption(
- CreationCollisionOption options)
+ private static NameCollisionOption GetWindowsNameCollisionOption(bool overwrite)
{
- return options switch
- {
- CreationCollisionOption.GenerateUniqueName => Windows.Storage.NameCollisionOption.GenerateUniqueName,
- CreationCollisionOption.ReplaceExisting => Windows.Storage.NameCollisionOption.ReplaceExisting,
- CreationCollisionOption.FailIfExists => Windows.Storage.NameCollisionOption.FailIfExists,
- _ => throw new ArgumentOutOfRangeException(nameof(options))
- };
+ return overwrite ? NameCollisionOption.ReplaceExisting : NameCollisionOption.GenerateUniqueName;
}
- private static Windows.Storage.CreationCollisionOption GetWindowsCreationCollisionOption(
- CreationCollisionOption options)
+ private static CreationCollisionOption GetWindowsCreationCollisionOption(bool overwrite)
{
- return options switch
- {
- CreationCollisionOption.GenerateUniqueName => Windows.Storage.CreationCollisionOption.GenerateUniqueName,
- CreationCollisionOption.ReplaceExisting => Windows.Storage.CreationCollisionOption.ReplaceExisting,
- CreationCollisionOption.OpenIfExists => Windows.Storage.CreationCollisionOption.OpenIfExists,
- CreationCollisionOption.FailIfExists => Windows.Storage.CreationCollisionOption.FailIfExists,
- _ => throw new ArgumentOutOfRangeException(nameof(options))
- };
+ return overwrite ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.OpenIfExists;
}
}
}
diff --git a/src/Files.App.Storage/WindowsStorage/WindowsStorageService.cs b/src/Files.App.Storage/WindowsStorage/WindowsStorageService.cs
index ef84ab20b802..f1ae043ba3d1 100644
--- a/src/Files.App.Storage/WindowsStorage/WindowsStorageService.cs
+++ b/src/Files.App.Storage/WindowsStorage/WindowsStorageService.cs
@@ -11,54 +11,20 @@
namespace Files.App.Storage.WindowsStorage
{
///
- public sealed class WindowsStorageService : IStorageService
+ internal sealed class WindowsStorageService : IStorageService
{
///
- public Task IsAccessibleAsync(CancellationToken cancellationToken = default)
+ public async Task GetFileAsync(string id, CancellationToken cancellationToken = default)
{
- return Task.FromResult(true);
- }
-
- ///
- public async Task FileExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- try
- {
- _ = await GetFileFromPathAsync(path, cancellationToken);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- ///
- public async Task DirectoryExistsAsync(string path, CancellationToken cancellationToken = default)
- {
- try
- {
- _ = await GetFolderFromPathAsync(path, cancellationToken);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
+ var file = await StorageFile.GetFileFromPathAsync(id).AsTask(cancellationToken);
+ return new WindowsStorageFile(file);
}
///
- public async Task GetFolderFromPathAsync(string path, CancellationToken cancellationToken = default)
+ public async Task GetFolderAsync(string id, CancellationToken cancellationToken = default)
{
- var folder = await StorageFolder.GetFolderFromPathAsync(path).AsTask(cancellationToken);
+ var folder = await StorageFolder.GetFolderFromPathAsync(id).AsTask(cancellationToken);
return new WindowsStorageFolder(folder);
}
-
- ///
- public async Task GetFileFromPathAsync(string path, CancellationToken cancellationToken = default)
- {
- var file = await StorageFile.GetFileFromPathAsync(path).AsTask(cancellationToken);
- return new WindowsStorageFile(file);
- }
}
}
diff --git a/src/Files.App/Actions/Content/Selection/ToggleSelectAction.cs b/src/Files.App/Actions/Content/Selection/ToggleSelectAction.cs
index debcccad239e..e31df5c99333 100644
--- a/src/Files.App/Actions/Content/Selection/ToggleSelectAction.cs
+++ b/src/Files.App/Actions/Content/Selection/ToggleSelectAction.cs
@@ -30,7 +30,7 @@ public Task ExecuteAsync()
private static SelectorItem? GetFocusedElement()
{
- return FocusManager.GetFocusedElement(App.Window.Content.XamlRoot) as SelectorItem;
+ return FocusManager.GetFocusedElement(MainWindow.Instance.Content.XamlRoot) as SelectorItem;
}
}
}
diff --git a/src/Files.App/Actions/Global/EnterCompactOverlayAction.cs b/src/Files.App/Actions/Global/EnterCompactOverlayAction.cs
index 53549a4b9f92..da0c35257317 100644
--- a/src/Files.App/Actions/Global/EnterCompactOverlayAction.cs
+++ b/src/Files.App/Actions/Global/EnterCompactOverlayAction.cs
@@ -34,9 +34,9 @@ public EnterCompactOverlayAction()
public Task ExecuteAsync()
{
- var window = App.GetAppWindow(App.Window);
- window.SetPresenter(AppWindowPresenterKind.CompactOverlay);
- window.Resize(new SizeInt32(400, 350));
+ var appWindow = MainWindow.Instance.AppWindow;
+ appWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
+ appWindow.Resize(new SizeInt32(400, 350));
return Task.CompletedTask;
}
diff --git a/src/Files.App/Actions/Global/ExitCompactOverlayAction.cs b/src/Files.App/Actions/Global/ExitCompactOverlayAction.cs
index 2f9d40798ea7..94abd73aef72 100644
--- a/src/Files.App/Actions/Global/ExitCompactOverlayAction.cs
+++ b/src/Files.App/Actions/Global/ExitCompactOverlayAction.cs
@@ -33,8 +33,8 @@ public ExitCompactOverlayAction()
public Task ExecuteAsync()
{
- var window = App.GetAppWindow(App.Window);
- window.SetPresenter(AppWindowPresenterKind.Overlapped);
+ var appWindow = MainWindow.Instance.AppWindow;
+ appWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
return Task.CompletedTask;
}
diff --git a/src/Files.App/Actions/Global/ToggleCompactOverlayAction.cs b/src/Files.App/Actions/Global/ToggleCompactOverlayAction.cs
index b3761896a0d7..135e10495bf4 100644
--- a/src/Files.App/Actions/Global/ToggleCompactOverlayAction.cs
+++ b/src/Files.App/Actions/Global/ToggleCompactOverlayAction.cs
@@ -31,16 +31,16 @@ public ToggleCompactOverlayAction()
public Task ExecuteAsync()
{
- var window = App.GetAppWindow(App.Window);
+ var appWindow = MainWindow.Instance.AppWindow;
if (windowContext.IsCompactOverlay)
{
- window.SetPresenter(AppWindowPresenterKind.Overlapped);
+ appWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
}
else
{
- window.SetPresenter(AppWindowPresenterKind.CompactOverlay);
- window.Resize(new SizeInt32(400, 350));
+ appWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay);
+ appWindow.Resize(new SizeInt32(400, 350));
}
return Task.CompletedTask;
diff --git a/src/Files.App/Actions/Global/ToggleFullScreenAction.cs b/src/Files.App/Actions/Global/ToggleFullScreenAction.cs
index b8dacab21d18..937d7888bc4a 100644
--- a/src/Files.App/Actions/Global/ToggleFullScreenAction.cs
+++ b/src/Files.App/Actions/Global/ToggleFullScreenAction.cs
@@ -20,22 +20,19 @@ public bool IsOn
{
get
{
- var window = App.GetAppWindow(App.Window);
-
- return window.Presenter.Kind is AppWindowPresenterKind.FullScreen;
+ var appWindow = MainWindow.Instance.AppWindow;
+ return appWindow.Presenter.Kind is AppWindowPresenterKind.FullScreen;
}
}
public Task ExecuteAsync()
{
- var window = App.GetAppWindow(App.Window);
-
- var newKind = window.Presenter.Kind is AppWindowPresenterKind.FullScreen
+ var appWindow = MainWindow.Instance.AppWindow;
+ var newKind = appWindow.Presenter.Kind is AppWindowPresenterKind.FullScreen
? AppWindowPresenterKind.Overlapped
: AppWindowPresenterKind.FullScreen;
- window.SetPresenter(newKind);
-
+ appWindow.SetPresenter(newKind);
return Task.CompletedTask;
}
}
diff --git a/src/Files.App/Actions/Open/OpenTerminalAction.cs b/src/Files.App/Actions/Open/OpenTerminalAction.cs
index d4ed04601266..b68d5c746ad8 100644
--- a/src/Files.App/Actions/Open/OpenTerminalAction.cs
+++ b/src/Files.App/Actions/Open/OpenTerminalAction.cs
@@ -37,7 +37,7 @@ public Task ExecuteAsync()
var terminalStartInfo = GetProcessStartInfo();
if (terminalStartInfo is not null)
{
- App.Window.DispatcherQueue.TryEnqueue(() =>
+ MainWindow.Instance.DispatcherQueue.TryEnqueue(() =>
{
try
{
diff --git a/src/Files.App/App.xaml.cs b/src/Files.App/App.xaml.cs
index 2fe19b26128d..615f1dfe7847 100644
--- a/src/Files.App/App.xaml.cs
+++ b/src/Files.App/App.xaml.cs
@@ -1,8 +1,6 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using CommunityToolkit.Mvvm.DependencyInjection;
-using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Helpers;
using CommunityToolkit.WinUI.Notifications;
using Files.App.Commands;
@@ -20,32 +18,21 @@
using Files.App.Storage.FtpStorage;
using Files.App.Storage.NativeStorage;
using Files.App.UserControls.MultitaskingControl;
-using Files.App.ViewModels;
using Files.App.ViewModels.Settings;
-using Files.App.Views;
using Files.Core.Services.SizeProvider;
using Files.Core.Storage;
using Files.Shared;
using Files.Shared.Cloud;
-using Files.Shared.Extensions;
using Files.Shared.Services;
using Files.Shared.Services.DateTimeFormatter;
-using Microsoft.AppCenter;
-using Microsoft.AppCenter.Analytics;
-using Microsoft.AppCenter.Crashes;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
-using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.AppLifecycle;
-using System;
-using System.Diagnostics;
using System.IO;
-using System.Linq;
using System.Text;
-using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage;
@@ -56,11 +43,13 @@ namespace Files.App
{
public partial class App : Application
{
+ private IHost? _host;
+
private static bool ShowErrorNotification = false;
- private IHost host { get; set; }
public static string OutputPath { get; set; }
public static CommandBarFlyout? LastOpenedFlyout { get; set; }
- public static StorageHistoryWrapper HistoryWrapper = new StorageHistoryWrapper();
+
+ public static StorageHistoryWrapper HistoryWrapper { get; } = new();
public static AppModel AppModel { get; private set; }
public static RecentItems RecentItemsManager { get; private set; }
public static QuickAccessManager QuickAccessManager { get; private set; }
@@ -70,38 +59,25 @@ public partial class App : Application
public static FileTagsManager FileTagsManager { get; private set; }
public static ILogger Logger { get; private set; }
- public static SecondaryTileHelper SecondaryTileHelper { get; private set; } = new SecondaryTileHelper();
-
- public static string AppVersion = $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}";
- public static string LogoPath;
- public static AppEnvironment AppEnv;
+ public static SecondaryTileHelper SecondaryTileHelper { get; private set; } = new();
///
- /// Initializes the singleton application object. This is the first line of authored code
+ /// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
///
public App()
{
- UnhandledException += OnUnhandledException;
- TaskScheduler.UnobservedTaskException += OnUnobservedException;
InitializeComponent();
-
- (AppEnv, LogoPath) = EnvHelpers.GetAppEnvironmentAndLogo();
+ EnsureEarlyApp();
}
- private static void EnsureSettingsAndConfigurationAreBootstrapped()
+ private void EnsureEarlyApp()
{
- RecentItemsManager ??= new RecentItems();
- AppModel ??= new AppModel();
- LibraryManager ??= new LibraryManager();
- CloudDrivesManager ??= new CloudDrivesManager();
- WSLDistroManager ??= new WSLDistroManager();
- FileTagsManager ??= new FileTagsManager();
- QuickAccessManager ??= new QuickAccessManager();
- }
+ // Configure exception handlers
+ UnhandledException += App_UnhandledException;
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+ TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
- private static Task StartAppCenter()
- {
#if STORE || STABLE || PREVIEW
try
{
@@ -114,83 +90,27 @@ private static Task StartAppCenter()
App.Logger.LogWarning(ex, "AppCenter could not be started.");
}
#endif
- return Task.CompletedTask;
- }
-
- private static async Task InitializeAppComponentsAsync()
- {
- var userSettingsService = Ioc.Default.GetRequiredService();
- var addItemService = Ioc.Default.GetRequiredService();
- var generalSettingsService = userSettingsService.GeneralSettingsService;
-
- // Start off a list of tasks we need to run before we can continue startup
- await Task.Run(async () =>
- {
- await Task.WhenAll(
- StartAppCenter(),
- OptionalTask(CloudDrivesManager.UpdateDrivesAsync(), generalSettingsService.ShowCloudDrivesSection),
- LibraryManager.UpdateLibrariesAsync(),
- OptionalTask(WSLDistroManager.UpdateDrivesAsync(), generalSettingsService.ShowWslSection),
- OptionalTask(FileTagsManager.UpdateFileTagsAsync(), generalSettingsService.ShowFileTagsSection),
- QuickAccessManager.InitializeAsync()
- );
-
- await Task.WhenAll(
- JumpListHelper.InitializeUpdatesAsync(),
- addItemService.GetNewEntriesAsync(),
- ContextMenu.WarmUpQueryContextMenuAsync()
- );
-
- FileTagsHelper.UpdateTagsDb();
- });
-
- // Check for required updates
- var updateService = Ioc.Default.GetRequiredService();
- await updateService.CheckForUpdates();
- await updateService.DownloadMandatoryUpdates();
- await updateService.CheckAndUpdateFilesLauncherAsync();
- await updateService.CheckLatestReleaseNotesAsync();
-
- static async Task OptionalTask(Task task, bool condition)
- {
- if (condition)
- await task;
- }
}
- ///
- /// Invoked when the application is launched normally by the end user. Other entry points
- /// will be used such as when the application is launched to open a specific file.
- ///
- /// Details about the launch request and process.
- protected override void OnLaunched(LaunchActivatedEventArgs e)
+ private IHost ConfigureHost()
{
- var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
-
- var logPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug.log");
- //start tracking app usage
- if (activatedEventArgs.Data is Windows.ApplicationModel.Activation.IActivatedEventArgs iaea)
- SystemInformation.Instance.TrackAppUse(iaea);
-
- // Initialize MainWindow here
- EnsureWindowIsInitialized();
- host = Host.CreateDefaultBuilder()
- .UseEnvironment(AppEnv.ToString())
- .ConfigureLogging(builder =>
+ return Host.CreateDefaultBuilder()
+ .UseEnvironment(ApplicationService.AppEnvironment.ToString())
+ .ConfigureLogging(builder =>
builder
- .AddProvider(new FileLoggerProvider(logPath))
- .SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information)
+ .AddProvider(new FileLoggerProvider(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug.log")))
+ .SetMinimumLevel(LogLevel.Information)
)
- .ConfigureServices(services =>
+ .ConfigureServices(services =>
services
.AddSingleton()
- .AddSingleton((sp) => new AppearanceSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new GeneralSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new FoldersSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new ApplicationSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new PreviewPaneSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new LayoutSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
- .AddSingleton((sp) => new AppSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new AppearanceSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new GeneralSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new FoldersSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new ApplicationSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new PreviewPaneSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new LayoutSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
+ .AddSingleton(sp => new AppSettingsService((sp.GetService() as UserSettingsService).GetSharingContext()))
.AddSingleton()
.AddSingleton()
.AddSingleton()
@@ -205,6 +125,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
.AddSingleton()
.AddSingleton()
.AddSingleton()
+ .AddSingleton()
#if UWP
.AddSingleton()
#else
@@ -237,44 +158,122 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
.AddSingleton()
)
.Build();
+ }
- Logger = host.Services.GetRequiredService>();
- App.Logger.LogInformation($"App launched. Launch args type: {activatedEventArgs.Data.GetType().Name}");
+ private static async Task InitializeAppComponentsAsync()
+ {
+ var userSettingsService = Ioc.Default.GetRequiredService();
+ var addItemService = Ioc.Default.GetRequiredService();
+ var generalSettingsService = userSettingsService.GeneralSettingsService;
- Ioc.Default.ConfigureServices(host.Services);
+ // Start off a list of tasks we need to run before we can continue startup
+ await Task.Run(async () =>
+ {
+ await Task.WhenAll(
+ OptionalTask(CloudDrivesManager.UpdateDrivesAsync(), generalSettingsService.ShowCloudDrivesSection),
+ LibraryManager.UpdateLibrariesAsync(),
+ OptionalTask(WSLDistroManager.UpdateDrivesAsync(), generalSettingsService.ShowWslSection),
+ OptionalTask(FileTagsManager.UpdateFileTagsAsync(), generalSettingsService.ShowFileTagsSection),
+ QuickAccessManager.InitializeAsync()
+ );
+
+ await Task.WhenAll(
+ JumpListHelper.InitializeUpdatesAsync(),
+ addItemService.GetNewEntriesAsync(),
+ ContextMenu.WarmUpQueryContextMenuAsync()
+ );
+
+ FileTagsHelper.UpdateTagsDb();
+ });
+
+ // Check for required updates
+ var updateService = Ioc.Default.GetRequiredService();
+ await updateService.CheckForUpdates();
+ await updateService.DownloadMandatoryUpdates();
+ await updateService.CheckAndUpdateFilesLauncherAsync();
+ await updateService.CheckLatestReleaseNotesAsync();
+
+ static async Task OptionalTask(Task task, bool condition)
+ {
+ if (condition)
+ await task;
+ }
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+ // Get AppActivationArguments
+ var appActivationArguments = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
+
+ // Start tracking app usage
+ if (appActivationArguments.Data is Windows.ApplicationModel.Activation.IActivatedEventArgs activationEventArgs)
+ SystemInformation.Instance.TrackAppUse(activationEventArgs);
+
+ // Configure Host and IoC
+ _host = ConfigureHost();
+ Ioc.Default.ConfigureServices(_host.Services);
EnsureSettingsAndConfigurationAreBootstrapped();
+ // Initialize and activate MainWindow
+ EnsureSuperEarlyWindow();
+
+ // TODO(s)
+ Logger = Ioc.Default.GetRequiredService>();
+ Logger.LogInformation($"App launched. Launch args type: {appActivationArguments.Data.GetType().Name}");
+
_ = InitializeAppComponentsAsync().ContinueWith(t => Logger.LogWarning(t.Exception, "Error during InitializeAppComponentsAsync()"), TaskContinuationOptions.OnlyOnFaulted);
+ _ = MainWindow.Instance.InitializeApplication(appActivationArguments.Data);
+ }
- _ = Window.InitializeApplication(activatedEventArgs.Data);
+ private static void EnsureSettingsAndConfigurationAreBootstrapped()
+ {
+ // TODO(s): Remove initialization here and move out all classes (visible below) out of App.xaml.cs
+
+ RecentItemsManager ??= new RecentItems();
+ AppModel ??= new AppModel();
+ LibraryManager ??= new LibraryManager();
+ CloudDrivesManager ??= new CloudDrivesManager();
+ WSLDistroManager ??= new WSLDistroManager();
+ FileTagsManager ??= new FileTagsManager();
+ QuickAccessManager ??= new QuickAccessManager();
}
- private void EnsureWindowIsInitialized()
+ private void EnsureSuperEarlyWindow()
{
- Window = new MainWindow();
- Window.Activated += Window_Activated;
- Window.Closed += Window_Closed;
- WindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(Window);
+ // Get the MainWindow instance
+ var window = MainWindow.Instance;
+
+ // Hook events for the window
+ window.Activated += Window_Activated;
+ window.Closed += Window_Closed;
+
+ // Attempt to activate it
+ window.Activate();
}
private void Window_Activated(object sender, WindowActivatedEventArgs args)
{
- if (args.WindowActivationState == WindowActivationState.CodeActivated ||
- args.WindowActivationState == WindowActivationState.PointerActivated)
- {
- ShowErrorNotification = true;
- ApplicationData.Current.LocalSettings.Values["INSTANCE_ACTIVE"] = -Process.GetCurrentProcess().Id;
- }
+ // TODO(s): Is this code still needed?
+ if (args.WindowActivationState is not (WindowActivationState.CodeActivated or WindowActivationState.PointerActivated))
+ return;
+
+ ShowErrorNotification = true;
+ ApplicationData.Current.LocalSettings.Values["INSTANCE_ACTIVE"] = -Process.GetCurrentProcess().Id;
}
public void OnActivated(AppActivationArguments activatedEventArgs)
{
- App.Logger.LogInformation($"App activated. Activated args type: {activatedEventArgs.Data.GetType().Name}");
+ Logger.LogInformation($"App activated. Activated args type: {activatedEventArgs.Data.GetType().Name}");
var data = activatedEventArgs.Data;
// InitializeApplication accesses UI, needs to be called on UI thread
- _ = Window.DispatcherQueue.EnqueueOrInvokeAsync(() => Window.InitializeApplication(data));
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => MainWindow.Instance.InitializeApplication(data));
}
///
@@ -359,24 +358,29 @@ public static void SaveSessionTabs()
.ToList();
}
+ #region Exception Handlers
+
///
/// Occurs when an exception is not handled on the UI thread.
///
///
///
- private static void OnUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
+ private static void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
=> AppUnhandledException(e.Exception, true);
+ private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
+ => AppUnhandledException(e.ExceptionObject as Exception, false);
+
///
/// Occurs when an exception is not handled on a background thread.
/// i.e. A task is fired and forgotten Task.Run(() => {...})
///
///
///
- private static void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
+ private static void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
=> AppUnhandledException(e.Exception, false);
- private static void AppUnhandledException(Exception ex, bool shouldShowNotification)
+ private static void AppUnhandledException(Exception? ex, bool shouldShowNotification)
{
StringBuilder formattedException = new StringBuilder() { Capacity = 200 };
@@ -480,7 +484,7 @@ private static void AppUnhandledException(Exception ex, bool shouldShowNotificat
userSettingsService.AppSettingsService.RestoreTabsOnStartup = true;
userSettingsService.GeneralSettingsService.LastCrashedTabList = lastSessionTabList;
- Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await Launcher.LaunchUriAsync(new Uri("files-uwp:"));
}).Wait(1000);
@@ -488,22 +492,6 @@ private static void AppUnhandledException(Exception ex, bool shouldShowNotificat
Process.GetCurrentProcess().Kill();
}
- public static void CloseApp()
- => Window.Close();
-
- public static AppWindow GetAppWindow(Window w)
- {
- var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(w);
-
- Microsoft.UI.WindowId windowId =
- Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
-
- return
- AppWindow.GetFromWindowId(windowId);
- }
-
- public static MainWindow Window { get; set; } = null!;
-
- public static IntPtr WindowHandle { get; private set; }
+ #endregion
}
}
diff --git a/src/Files.App/Contexts/Window/WindowContext.cs b/src/Files.App/Contexts/Window/WindowContext.cs
index 208c5db61655..6c6847307c3e 100644
--- a/src/Files.App/Contexts/Window/WindowContext.cs
+++ b/src/Files.App/Contexts/Window/WindowContext.cs
@@ -13,7 +13,7 @@ internal class WindowContext : ObservableObject, IWindowContext
public WindowContext()
{
- App.Window.PresenterChanged += Window_PresenterChanged;
+ MainWindow.Instance.PresenterChanged += Window_PresenterChanged;
}
private void Window_PresenterChanged(object? sender, AppWindowPresenter e)
diff --git a/src/Files.App/Data/Items/DriveItem.cs b/src/Files.App/Data/Items/DriveItem.cs
index 4b635fd44b22..0421a456f5be 100644
--- a/src/Files.App/Data/Items/DriveItem.cs
+++ b/src/Files.App/Data/Items/DriveItem.cs
@@ -1,11 +1,11 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using ByteSizeLib;
using Files.App.Storage.WindowsStorage;
using Files.Core.Storage;
using Files.Core.Storage.Enums;
using Files.Core.Storage.LocatableStorage;
+using Files.Core.Storage.NestedStorage;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Storage;
@@ -178,7 +178,7 @@ public static async Task CreateFromPropertiesAsync(StorageFolder root
item.DeviceID = deviceId;
item.Root = root;
- _ = App.Window.DispatcherQueue.EnqueueOrInvokeAsync(item.UpdatePropertiesAsync);
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(item.UpdatePropertiesAsync);
return item;
}
@@ -268,25 +268,25 @@ private string GetSizeString()
MaxSpace.ToSizeString());
}
- public Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
+ public Task GetFileAsync(string fileName, CancellationToken cancellationToken = default)
{
var folder = new WindowsStorageFolder(Root);
return folder.GetFileAsync(fileName, cancellationToken);
}
- public Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
+ public Task GetFolderAsync(string folderName, CancellationToken cancellationToken = default)
{
var folder = new WindowsStorageFolder(Root);
return folder.GetFolderAsync(folderName, cancellationToken);
}
- public IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, CancellationToken cancellationToken = default)
+ public IAsyncEnumerable GetItemsAsync(StorableKind kind = StorableKind.All, CancellationToken cancellationToken = default)
{
var folder = new WindowsStorageFolder(Root);
return folder.GetItemsAsync(kind, cancellationToken);
}
- public Task GetParentAsync(CancellationToken cancellationToken = default)
+ public Task GetParentAsync(CancellationToken cancellationToken = default)
{
var folder = new WindowsStorageFolder(Root);
return folder.GetParentAsync(cancellationToken);
diff --git a/src/Files.App/Data/Items/LocationItem.cs b/src/Files.App/Data/Items/LocationItem.cs
index 1256ebfb4b0f..e8bb1cce6524 100644
--- a/src/Files.App/Data/Items/LocationItem.cs
+++ b/src/Files.App/Data/Items/LocationItem.cs
@@ -92,7 +92,7 @@ public ulong SpaceUsed
{
SetProperty(ref spaceUsed, value);
- App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => OnPropertyChanged(nameof(ToolTipText)));
+ MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => OnPropertyChanged(nameof(ToolTipText)));
}
}
diff --git a/src/Files.App/Data/Models/AppModel.cs b/src/Files.App/Data/Models/AppModel.cs
index da251030e220..07ca46926daa 100644
--- a/src/Files.App/Data/Models/AppModel.cs
+++ b/src/Files.App/Data/Models/AppModel.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using Files.App.Views;
using Microsoft.UI.Xaml.Controls;
using Windows.ApplicationModel.DataTransfer;
@@ -9,11 +8,8 @@ namespace Files.App.Data.Models
{
public class AppModel : ObservableObject
{
- private IFoldersSettingsService FoldersSettings;
-
public AppModel()
{
- FoldersSettings = Ioc.Default.GetRequiredService().FoldersSettingsService;
Clipboard.ContentChanged += Clipboard_ContentChanged;
}
@@ -46,7 +42,7 @@ public int TabStripSelectedIndex
if (value < MainPageViewModel.AppInstances.Count)
{
- Frame rootFrame = (Frame)App.Window.Content;
+ Frame rootFrame = (Frame)MainWindow.Instance.Content;
var mainView = (MainPage)rootFrame.Content;
mainView.ViewModel.SelectedTabItem = MainPageViewModel.AppInstances[value];
}
diff --git a/src/Files.App/Data/Models/SidebarPinnedModel.cs b/src/Files.App/Data/Models/SidebarPinnedModel.cs
index 257d3e79adf1..15e8f26c2a55 100644
--- a/src/Files.App/Data/Models/SidebarPinnedModel.cs
+++ b/src/Files.App/Data/Models/SidebarPinnedModel.cs
@@ -109,7 +109,7 @@ public async Task CreateLocationItemFromPathAsync(string path)
locationItem.IconData = iconData;
if (locationItem.IconData is not null)
- locationItem.Icon = await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => locationItem.IconData.ToBitmapAsync());
+ locationItem.Icon = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => locationItem.IconData.ToBitmapAsync());
}
if (locationItem.IconData is null)
@@ -117,12 +117,12 @@ public async Task CreateLocationItemFromPathAsync(string path)
locationItem.IconData = await FileThumbnailHelper.LoadIconWithoutOverlayAsync(path, 48u);
if (locationItem.IconData is not null)
- locationItem.Icon = await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => locationItem.IconData.ToBitmapAsync());
+ locationItem.Icon = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => locationItem.IconData.ToBitmapAsync());
}
}
else
{
- locationItem.Icon = await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => UIHelpers.GetSidebarIconResource(Constants.ImageRes.Folder));
+ locationItem.Icon = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => UIHelpers.GetSidebarIconResource(Constants.ImageRes.Folder));
locationItem.IsInvalid = true;
Debug.WriteLine($"Pinned item was invalid {res.ErrorCode}, item: {path}");
}
diff --git a/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs b/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs
index 6b0e256fc777..132bd386442c 100644
--- a/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs
+++ b/src/Files.App/Dialogs/CreateArchiveDialog.xaml.cs
@@ -62,7 +62,7 @@ public CreateArchiveDialog()
private static ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
{
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
- contentDialog.XamlRoot = App.Window.Content.XamlRoot; // WinUi3
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot; // WinUi3
return contentDialog;
}
diff --git a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs
index 000800738d72..a7bb94deb52b 100644
--- a/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs
+++ b/src/Files.App/Dialogs/FilesystemOperationDialog.xaml.cs
@@ -36,7 +36,7 @@ public FilesystemOperationDialog()
{
InitializeComponent();
- App.Window.SizeChanged += Current_SizeChanged;
+ MainWindow.Instance.SizeChanged += Current_SizeChanged;
}
public new async Task ShowAsync() => (DialogResult)await SetContentDialogRoot(this).ShowAsync();
@@ -46,7 +46,7 @@ private ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
{
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
- contentDialog.XamlRoot = App.Window.Content.XamlRoot;
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
}
return contentDialog;
}
@@ -59,7 +59,7 @@ private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
private void UpdateDialogLayout()
{
if (ViewModel.FileSystemDialogMode.ConflictsExist)
- ContainerGrid.Width = App.Window.Bounds.Width <= 700 ? App.Window.Bounds.Width - 50 : 650;
+ ContainerGrid.Width = MainWindow.Instance.Bounds.Width <= 700 ? MainWindow.Instance.Bounds.Width - 50 : 650;
}
protected override void OnApplyTemplate()
@@ -87,7 +87,7 @@ private void RootDialog_Closing(ContentDialog sender, ContentDialogClosingEventA
if (args.Result == ContentDialogResult.Primary)
ViewModel.SaveConflictResolveOption();
- App.Window.SizeChanged -= Current_SizeChanged;
+ MainWindow.Instance.SizeChanged -= Current_SizeChanged;
ViewModel.CancelCts();
}
diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml.cs b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
index d66be9a6e900..6ad9e8aaa0e8 100644
--- a/src/Files.App/Dialogs/SettingsDialog.xaml.cs
+++ b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
@@ -16,13 +16,13 @@ public sealed partial class SettingsDialog : ContentDialog, IDialog (FrameworkElement)App.Window.Content;
+ => (FrameworkElement)MainWindow.Instance.Content;
public SettingsDialog()
{
InitializeComponent();
- App.Window.SizeChanged += Current_SizeChanged;
+ MainWindow.Instance.SizeChanged += Current_SizeChanged;
UpdateDialogLayout();
}
@@ -36,9 +36,9 @@ private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
private void UpdateDialogLayout()
{
- ContainerGrid.Height = App.Window.Bounds.Height <= 760 ? App.Window.Bounds.Height - 70 : 690;
- ContainerGrid.Width = App.Window.Bounds.Width <= 1100 ? App.Window.Bounds.Width : 1100;
- MainSettingsNavigationView.PaneDisplayMode = App.Window.Bounds.Width < 700 ? NavigationViewPaneDisplayMode.LeftCompact : NavigationViewPaneDisplayMode.Left;
+ ContainerGrid.Height = MainWindow.Instance.Bounds.Height <= 760 ? MainWindow.Instance.Bounds.Height - 70 : 690;
+ ContainerGrid.Width = MainWindow.Instance.Bounds.Width <= 1100 ? MainWindow.Instance.Bounds.Width : 1100;
+ MainSettingsNavigationView.PaneDisplayMode = MainWindow.Instance.Bounds.Width < 700 ? NavigationViewPaneDisplayMode.LeftCompact : NavigationViewPaneDisplayMode.Left;
}
private void MainSettingsNavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
@@ -60,7 +60,7 @@ private void MainSettingsNavigationView_SelectionChanged(NavigationView sender,
private void ContentDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
{
- App.Window.SizeChanged -= Current_SizeChanged;
+ MainWindow.Instance.SizeChanged -= Current_SizeChanged;
}
private void CloseSettingsDialogButton_Click(object sender, RoutedEventArgs e)
diff --git a/src/Files.App/Helpers/Dialog/DialogDisplayHelper.cs b/src/Files.App/Helpers/Dialog/DialogDisplayHelper.cs
index 29489d9f66eb..1b3c47893858 100644
--- a/src/Files.App/Helpers/Dialog/DialogDisplayHelper.cs
+++ b/src/Files.App/Helpers/Dialog/DialogDisplayHelper.cs
@@ -49,7 +49,7 @@ public static async Task ShowDialogAsync(DynamicDialog dial
{
try
{
- if (App.Window.Content is Frame rootFrame)
+ if (MainWindow.Instance.Content is Frame rootFrame)
{
await dialog.ShowAsync();
return dialog.DynamicResult;
diff --git a/src/Files.App/Helpers/Environment/EnvHelpers.cs b/src/Files.App/Helpers/Environment/EnvHelpers.cs
deleted file mode 100644
index 8ee9f44b5b9b..000000000000
--- a/src/Files.App/Helpers/Environment/EnvHelpers.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2023 Files Community
-// Licensed under the MIT License. See the LICENSE.
-
-namespace Files.App.Helpers
-{
- public static class EnvHelpers
- {
-
- public static (AppEnvironment, string) GetAppEnvironmentAndLogo()
- {
-
-
- var env =
-#if STORE
- AppEnvironment.Store;
-#elif PREVIEW
- AppEnvironment.Preview;
-#elif STABLE
- AppEnvironment.Stable;
-#else
- AppEnvironment.Dev;
-#endif
-
- var path = env switch
- {
- AppEnvironment.Dev => Constants.AssetPaths.DevLogo,
- AppEnvironment.Preview => Constants.AssetPaths.PreviewLogo,
- _ => Constants.AssetPaths.StableLogo,
- };
-
- return (env, path);
- }
- }
-}
diff --git a/src/Files.App/Helpers/Interop/NativeWinApiHelper.cs b/src/Files.App/Helpers/Interop/NativeWinApiHelper.cs
index 0b93a9c378a0..adf5214b6114 100644
--- a/src/Files.App/Helpers/Interop/NativeWinApiHelper.cs
+++ b/src/Files.App/Helpers/Interop/NativeWinApiHelper.cs
@@ -3,10 +3,8 @@
using Files.App.Utils.Shell;
using Microsoft.Extensions.Logging;
-using System;
using System.Runtime.InteropServices;
using System.Text;
-using System.Threading.Tasks;
using Windows.Foundation.Metadata;
using Windows.System;
@@ -258,17 +256,6 @@ public static bool IsHasThreadAccessPropertyPresent
}
}
- // https://www.travelneil.com/wndproc-in-uwp.html
- [ComImport, System.Runtime.InteropServices.Guid("45D64A29-A63E-4CB6-B498-5781D298CB4F")]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- internal interface ICoreWindowInterop
- {
- IntPtr WindowHandle { get; }
- bool MessageHandled { get; }
- }
-
- public static IntPtr CoreWindowHandle => App.WindowHandle;
-
public static Task GetFileAssociationAsync(string filePath)
=> Win32API.GetFileAssociationAsync(filePath, true);
}
diff --git a/src/Files.App/Helpers/MenuFlyout/ShellContextMenuHelper.cs b/src/Files.App/Helpers/MenuFlyout/ShellContextMenuHelper.cs
index c93f1cd51995..0c2ec5425091 100644
--- a/src/Files.App/Helpers/MenuFlyout/ShellContextMenuHelper.cs
+++ b/src/Files.App/Helpers/MenuFlyout/ShellContextMenuHelper.cs
@@ -276,7 +276,7 @@ public static async Task LoadShellMenuItems(
var (_, secondaryElements) = ItemModelListToContextFlyoutHelper.GetAppBarItemsFromModel(shellMenuItems);
if (secondaryElements.Any())
{
- var openedPopups = Microsoft.UI.Xaml.Media.VisualTreeHelper.GetOpenPopups(App.Window);
+ var openedPopups = Microsoft.UI.Xaml.Media.VisualTreeHelper.GetOpenPopups(MainWindow.Instance);
var secondaryMenu = openedPopups.FirstOrDefault(popup => popup.Name == "OverflowPopup");
var itemsControl = secondaryMenu?.Child.FindDescendant();
diff --git a/src/Files.App/Helpers/Navigation/NavigationHelpers.cs b/src/Files.App/Helpers/Navigation/NavigationHelpers.cs
index 170f74e7d4ad..04e5c0a30420 100644
--- a/src/Files.App/Helpers/Navigation/NavigationHelpers.cs
+++ b/src/Files.App/Helpers/Navigation/NavigationHelpers.cs
@@ -431,7 +431,7 @@ private static async Task OpenFile(string path, IShellPage ass
// WINUI3
private static LauncherOptions InitializeWithWindow(LauncherOptions obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/Helpers/ShareItemHelpers.cs b/src/Files.App/Helpers/ShareItemHelpers.cs
index 165913cd14ad..98390fa5027e 100644
--- a/src/Files.App/Helpers/ShareItemHelpers.cs
+++ b/src/Files.App/Helpers/ShareItemHelpers.cs
@@ -23,12 +23,12 @@ public static bool IsItemShareable(ListedItem item)
public static void ShareItems(IEnumerable itemsToShare)
{
var interop = DataTransferManager.As();
- IntPtr result = interop.GetForWindow(App.WindowHandle, InteropHelpers.DataTransferManagerInteropIID);
+ IntPtr result = interop.GetForWindow(MainWindow.Instance.WindowHandle, InteropHelpers.DataTransferManagerInteropIID);
var manager = WinRT.MarshalInterface.FromAbi(result);
manager.DataRequested += new TypedEventHandler(Manager_DataRequested);
- interop.ShowShareUIForWindow(App.WindowHandle);
+ interop.ShowShareUIForWindow(MainWindow.Instance.WindowHandle);
async void Manager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
diff --git a/src/Files.App/Helpers/Storage/FilePropertiesHelpers.cs b/src/Files.App/Helpers/Storage/FilePropertiesHelpers.cs
index 98c5ace67217..71d5ad72ec93 100644
--- a/src/Files.App/Helpers/Storage/FilePropertiesHelpers.cs
+++ b/src/Files.App/Helpers/Storage/FilePropertiesHelpers.cs
@@ -5,12 +5,9 @@
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.Windows.ApplicationModel.Resources;
using System.Collections.Concurrent;
-using System.IO;
-using Windows.ApplicationModel;
using Windows.Graphics;
namespace Files.App.Helpers
@@ -26,12 +23,6 @@ public static class FilePropertiesHelpers
public static readonly bool FlowDirectionSettingIsRightToLeft =
new ResourceManager().CreateResourceContext().QualifierValues["LayoutDirection"] == "RTL";
- ///
- /// App logo location to use as window popup icon and title bar icon
- ///
- public static string LogoPath
- => Path.Combine(Package.Current.InstalledLocation.Path, App.LogoPath);
-
///
/// Get window handle (hWnd) of the given properties window instance
///
@@ -93,6 +84,8 @@ public static void OpenPropertiesWindow(IShellPage associatedInstance)
/// Associated main window instance
public static void OpenPropertiesWindow(object item, IShellPage associatedInstance)
{
+ var applicationService = Ioc.Default.GetRequiredService();
+
if (item is null)
return;
@@ -123,7 +116,7 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan
appWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
appWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
- appWindow.SetIcon(LogoPath);
+ appWindow.SetIcon(applicationService.AppIcoPath);
frame.Navigate(
typeof(Views.Properties.MainPropertiesPage),
diff --git a/src/Files.App/Helpers/UI/SecondaryTileHelper.cs b/src/Files.App/Helpers/UI/SecondaryTileHelper.cs
index b84dbe0247d0..f56ff259e114 100644
--- a/src/Files.App/Helpers/UI/SecondaryTileHelper.cs
+++ b/src/Files.App/Helpers/UI/SecondaryTileHelper.cs
@@ -63,7 +63,7 @@ public async Task TryPinFolderAsync(string path, string name)
}
private SecondaryTile InitializeWithWindow(SecondaryTile obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/Helpers/UI/ThemeHelper.cs b/src/Files.App/Helpers/UI/ThemeHelper.cs
index 24bf6bc6b513..202026e4a2d9 100644
--- a/src/Files.App/Helpers/UI/ThemeHelper.cs
+++ b/src/Files.App/Helpers/UI/ThemeHelper.cs
@@ -1,10 +1,6 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using CommunityToolkit.Mvvm.DependencyInjection;
-using CommunityToolkit.WinUI;
-using Files.App.Extensions;
-using Files.App.ViewModels;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
@@ -49,11 +45,11 @@ public static ElementTheme RootTheme
public static void Initialize()
{
// Save reference as this might be null when the user is in another app
- currentApplicationWindow = App.Window;
+ currentApplicationWindow = MainWindow.Instance;
// Set TitleBar background color
if (currentApplicationWindow is not null)
- titleBar = App.GetAppWindow(currentApplicationWindow)?.TitleBar;
+ titleBar = MainWindow.Instance.AppWindow.TitleBar;
// Apply the desired theme based on what is set in the application settings
ApplyTheme();
@@ -68,14 +64,13 @@ private static async void UiSettings_ColorValuesChanged(UISettings sender, objec
// Make sure we have a reference to our window so we dispatch a UI change
if (currentApplicationWindow is null)
{
- currentApplicationWindow = App.Window;
+ currentApplicationWindow = MainWindow.Instance;
if (currentApplicationWindow is null)
return;
}
- if (titleBar is null)
- titleBar = App.GetAppWindow(currentApplicationWindow)?.TitleBar;
+ titleBar ??= MainWindow.Instance.AppWindow.TitleBar;
// Dispatch on UI thread so that we have a current appbar to access and change
await currentApplicationWindow.DispatcherQueue.EnqueueOrInvokeAsync(ApplyTheme);
@@ -85,7 +80,7 @@ private static void ApplyTheme()
{
var rootTheme = RootTheme;
- if (App.Window.Content is FrameworkElement rootElement)
+ if (MainWindow.Instance.Content is FrameworkElement rootElement)
rootElement.RequestedTheme = rootTheme;
if (titleBar is not null)
diff --git a/src/Files.App/Helpers/UI/UIHelpers.cs b/src/Files.App/Helpers/UI/UIHelpers.cs
index e83833d9219a..62fc05f63925 100644
--- a/src/Files.App/Helpers/UI/UIHelpers.cs
+++ b/src/Files.App/Helpers/UI/UIHelpers.cs
@@ -123,14 +123,14 @@ private static ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
{
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
- contentDialog.XamlRoot = App.Window.Content.XamlRoot;
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
}
return contentDialog;
}
public static void CloseAllDialogs()
{
- var openedDialogs = VisualTreeHelper.GetOpenPopups(App.Window);
+ var openedDialogs = VisualTreeHelper.GetOpenPopups(MainWindow.Instance);
foreach (var item in openedDialogs)
{
diff --git a/src/Files.App/Interacts/BaseLayoutCommandImplementationModel.cs b/src/Files.App/Interacts/BaseLayoutCommandImplementationModel.cs
index e254b866f6ce..9ecd20778002 100644
--- a/src/Files.App/Interacts/BaseLayoutCommandImplementationModel.cs
+++ b/src/Files.App/Interacts/BaseLayoutCommandImplementationModel.cs
@@ -62,7 +62,7 @@ public virtual async Task OpenDirectoryInNewTab(RoutedEventArgs e)
{
foreach (ListedItem listedItem in SlimContentPage.SelectedItems)
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await mainPageViewModel.AddNewTabByPathAsync(typeof(PaneHolderPage), (listedItem as ShortcutItem)?.TargetPath ?? listedItem.ItemPath);
},
diff --git a/src/Files.App/MainWindow.xaml.cs b/src/Files.App/MainWindow.xaml.cs
index 6dfc1310d3b5..05bd29028ebc 100644
--- a/src/Files.App/MainWindow.xaml.cs
+++ b/src/Files.App/MainWindow.xaml.cs
@@ -18,24 +18,33 @@ namespace Files.App
{
public sealed partial class MainWindow : WindowEx
{
+ private static MainWindow? _Instance;
+ public static MainWindow Instance => _Instance ??= new();
+
+ public IntPtr WindowHandle { get; }
+
private MainPageViewModel mainPageViewModel;
- public MainWindow()
- {
- InitializeComponent();
+ private IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService();
- PersistenceId = "FilesMainWindow";
+ private MainWindow()
+ {
+ WindowHandle = this.GetWindowHandle();
+ InitializeComponent();
EnsureEarlyWindow();
}
private void EnsureEarlyWindow()
{
+ // Set PersistenceId
+ PersistenceId = "FilesMainWindow";
+
// Set title
AppWindow.Title = "Files";
// Set logo
- AppWindow.SetIcon(Path.Combine(Package.Current.InstalledLocation.Path, App.LogoPath));
+ AppWindow.SetIcon(Path.Combine(Package.Current.InstalledLocation.Path, ApplicationService.AppIcoPath));
// Extend title bar
AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;
@@ -160,7 +169,7 @@ private Frame EnsureWindowIsInitialized()
// NOTE:
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
- if (!(App.Window.Content is Frame rootFrame))
+ if (!(MainWindow.Instance.Content is Frame rootFrame))
{
// Set system backdrop
this.SystemBackdrop = new AppSystemBackdrop();
@@ -171,7 +180,7 @@ private Frame EnsureWindowIsInitialized()
rootFrame.NavigationFailed += OnNavigationFailed;
// Place the frame in the current Window
- App.Window.Content = rootFrame;
+ MainWindow.Instance.Content = rootFrame;
}
return rootFrame;
diff --git a/src/Files.App/Program.cs b/src/Files.App/Program.cs
index 9ed6d5a7a813..5c40f054606a 100644
--- a/src/Files.App/Program.cs
+++ b/src/Files.App/Program.cs
@@ -1,8 +1,6 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using Files.App.Utils.Shell;
-using Files.Core.Helpers;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
diff --git a/src/Files.App/Services/ApplicationService.cs b/src/Files.App/Services/ApplicationService.cs
new file mode 100644
index 000000000000..b9148741640e
--- /dev/null
+++ b/src/Files.App/Services/ApplicationService.cs
@@ -0,0 +1,38 @@
+using Windows.ApplicationModel;
+
+namespace Files.App.Services
+{
+ ///
+ internal sealed class ApplicationService : IApplicationService
+ {
+ // Workaround to help improve code clarity
+ internal static readonly AppEnvironment AppEnvironment =
+#if STORE
+ AppEnvironment.Store;
+#elif PREVIEW
+ AppEnvironment.Preview;
+#elif STABLE
+ AppEnvironment.Stable;
+#else
+ AppEnvironment.Dev;
+#endif
+
+ ///
+ public AppEnvironment Environment { get; } = AppEnvironment;
+
+ ///
+ public Version AppVersion { get; } = new(
+ Package.Current.Id.Version.Major,
+ Package.Current.Id.Version.Minor,
+ Package.Current.Id.Version.Build,
+ Package.Current.Id.Version.Revision);
+
+ ///
+ public string AppIcoPath { get; } = AppEnvironment switch
+ {
+ AppEnvironment.Dev => Constants.AssetPaths.DevLogo,
+ AppEnvironment.Preview => Constants.AssetPaths.PreviewLogo,
+ _ => Constants.AssetPaths.StableLogo
+ };
+ }
+}
diff --git a/src/Files.App/Services/DialogService.cs b/src/Files.App/Services/DialogService.cs
index a1bbadfbb75a..7dc577fdb613 100644
--- a/src/Files.App/Services/DialogService.cs
+++ b/src/Files.App/Services/DialogService.cs
@@ -50,7 +50,7 @@ public IDialog GetDialog(TViewModel viewModel)
dialog.ViewModel = viewModel;
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
- contentDialog.XamlRoot = App.Window.Content.XamlRoot;
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
return dialog;
}
diff --git a/src/Files.App/Services/FileExplorerService.cs b/src/Files.App/Services/FileExplorerService.cs
index b371b730b901..913dff5372e1 100644
--- a/src/Files.App/Services/FileExplorerService.cs
+++ b/src/Files.App/Services/FileExplorerService.cs
@@ -43,7 +43,7 @@ public Task OpenInFileExplorerAsync(ILocatableFolder folder, CancellationToken c
// WINUI3
private FileOpenPicker InitializeWithWindow(FileOpenPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
@@ -63,7 +63,7 @@ private FileOpenPicker InitializeWithWindow(FileOpenPicker obj)
// WINUI3
private FolderPicker InitializeWithWindow(FolderPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/Services/FileTagsService.cs b/src/Files.App/Services/FileTagsService.cs
index 7b09fa491d4e..a0cc589a86ba 100644
--- a/src/Files.App/Services/FileTagsService.cs
+++ b/src/Files.App/Services/FileTagsService.cs
@@ -13,7 +13,7 @@ internal sealed class FileTagsService : IFileTagsService
{
private IStorageService StorageService { get; } = Ioc.Default.GetRequiredService();
- private readonly IFileTagsSettingsService FileTagsSettingsService = Ioc.Default.GetRequiredService();
+ private IFileTagsSettingsService FileTagsSettingsService { get; } = Ioc.Default.GetRequiredService();
///
public Task IsSupportedAsync()
@@ -45,7 +45,7 @@ public async IAsyncEnumerable GetItemsForTagAsync(string tagUid
if (!item.Tags.Contains(tagUid))
continue;
- var storable = await StorageService.TryGetStorableFromPathAsync(item.FilePath, cancellationToken);
+ var storable = await StorageService.TryGetStorableAsync(item.FilePath, cancellationToken);
if (storable is null)
continue;
@@ -60,7 +60,7 @@ public async IAsyncEnumerable GetAllFileTagsAsync([EnumeratorCa
{
foreach (var item in FileTagsHelper.GetDbInstance().GetAll())
{
- var storable = await StorageService.TryGetStorableFromPathAsync(item.FilePath, cancellationToken);
+ var storable = await StorageService.TryGetStorableAsync(item.FilePath, cancellationToken);
if (storable is null)
continue;
diff --git a/src/Files.App/Services/NetworkDrivesService.cs b/src/Files.App/Services/NetworkDrivesService.cs
index 954f3b6ed1ac..c4bd426f9aa7 100644
--- a/src/Files.App/Services/NetworkDrivesService.cs
+++ b/src/Files.App/Services/NetworkDrivesService.cs
@@ -66,7 +66,7 @@ public async IAsyncEnumerable GetDrivesAsync()
public Task OpenMapNetworkDriveDialogAsync()
{
- var handle = NativeWinApiHelper.CoreWindowHandle.ToInt64();
+ var handle = MainWindow.Instance.WindowHandle.ToInt64();
return NetworkDrivesAPI.OpenMapNetworkDriveDialog(handle);
}
}
diff --git a/src/Files.App/Services/RemovableDrivesService.cs b/src/Files.App/Services/RemovableDrivesService.cs
index e5442bd5689d..6bd33c17e1fa 100644
--- a/src/Files.App/Services/RemovableDrivesService.cs
+++ b/src/Files.App/Services/RemovableDrivesService.cs
@@ -57,7 +57,7 @@ public async Task UpdateDrivePropertiesAsync(ILocatableFolder drive)
var rootModified = await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(drive.Path).AsTask());
if (rootModified && drive is DriveItem matchingDriveEjected)
{
- _ = App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
matchingDriveEjected.Root = rootModified.Result;
matchingDriveEjected.Text = rootModified.Result.DisplayName;
diff --git a/src/Files.App/Services/Settings/FileTagsSettingsService.cs b/src/Files.App/Services/Settings/FileTagsSettingsService.cs
index 992467643471..98ee8aa1be1d 100644
--- a/src/Files.App/Services/Settings/FileTagsSettingsService.cs
+++ b/src/Files.App/Services/Settings/FileTagsSettingsService.cs
@@ -9,10 +9,7 @@
using Files.Core.Services.Settings;
using Files.Core.ViewModels.FileTags;
using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
using Windows.Storage;
namespace Files.App.Services.Settings
@@ -90,11 +87,6 @@ public IEnumerable GetTagsByName(string tagName)
return FileTagList.Where(x => x.Name.Equals(tagName, StringComparison.OrdinalIgnoreCase));
}
- public IEnumerable SearchTagsByName(string tagName)
- {
- return FileTagList.Where(x => x.Name.StartsWith(tagName, StringComparison.OrdinalIgnoreCase));
- }
-
public void CreateNewTag(string newTagName, string color)
{
var newTag = new TagViewModel(
diff --git a/src/Files.App/Services/UpdateService.cs b/src/Files.App/Services/UpdateService.cs
index b18fb3ca8d11..3df30a1e206d 100644
--- a/src/Files.App/Services/UpdateService.cs
+++ b/src/Files.App/Services/UpdateService.cs
@@ -118,7 +118,7 @@ private async Task GetUpdatePackages()
{
_storeContext ??= await Task.Run(StoreContext.GetDefault);
- InitializeWithWindow.Initialize(_storeContext, App.WindowHandle);
+ InitializeWithWindow.Initialize(_storeContext, MainWindow.Instance.WindowHandle);
var updateList = await _storeContext.GetAppAndOptionalStorePackageUpdatesAsync();
_updatePackages = updateList?.ToList();
diff --git a/src/Files.App/UserControls/MultitaskingControl/BaseMultitaskingControl.cs b/src/Files.App/UserControls/MultitaskingControl/BaseMultitaskingControl.cs
index 2cc0a680e82b..c86c938f495b 100644
--- a/src/Files.App/UserControls/MultitaskingControl/BaseMultitaskingControl.cs
+++ b/src/Files.App/UserControls/MultitaskingControl/BaseMultitaskingControl.cs
@@ -147,7 +147,7 @@ public void CloseTab(TabItem tabItem)
{
if (Items.Count == 1)
{
- App.CloseApp();
+ MainWindow.Instance.Close();
}
else if (Items.Count > 1)
{
diff --git a/src/Files.App/UserControls/MultitaskingControl/HorizontalMultitaskingControl.xaml.cs b/src/Files.App/UserControls/MultitaskingControl/HorizontalMultitaskingControl.xaml.cs
index 0ea02b4e4a99..3f873e4c772a 100644
--- a/src/Files.App/UserControls/MultitaskingControl/HorizontalMultitaskingControl.xaml.cs
+++ b/src/Files.App/UserControls/MultitaskingControl/HorizontalMultitaskingControl.xaml.cs
@@ -1,16 +1,11 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.WinUI.UI;
using Files.App.Commands;
-using Files.App.Extensions;
-using Files.App.Helpers;
-using Files.App.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Shapes;
-using System;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage;
@@ -33,8 +28,8 @@ public HorizontalMultitaskingControl()
tabHoverTimer.Interval = TimeSpan.FromMilliseconds(500);
tabHoverTimer.Tick += TabHoverSelected;
- var appWindowTitleBar = App.GetAppWindow(App.Window).TitleBar;
- double rightPaddingColumnWidth = FilePropertiesHelpers.FlowDirectionSettingIsRightToLeft ? appWindowTitleBar.LeftInset : appWindowTitleBar.RightInset;
+ var appWindow = MainWindow.Instance.AppWindow;
+ double rightPaddingColumnWidth = FilePropertiesHelpers.FlowDirectionSettingIsRightToLeft ? appWindow.TitleBar.LeftInset : appWindow.TitleBar.RightInset;
RightPaddingColumn.Width = new GridLength(rightPaddingColumnWidth >= 0 ? rightPaddingColumnWidth : 0);
}
diff --git a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs
index ae10e1145bda..f8c9fa481b05 100644
--- a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs
+++ b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs
@@ -52,7 +52,7 @@ public async Task LoadCardThumbnailAsync()
// Thumbnail data is valid, set the item icon
if (thumbnailData is not null && thumbnailData.Length > 0)
- Thumbnail = await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(Constants.Widgets.WidgetIconSize));
+ Thumbnail = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(Constants.Widgets.WidgetIconSize));
}
public int CompareTo(DriveCardItem? other) => Item.Path.CompareTo(other?.Item?.Path);
diff --git a/src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs b/src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs
index 5ef981e6a46f..1ca835fe7cff 100644
--- a/src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs
+++ b/src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs
@@ -100,7 +100,7 @@ public async Task LoadCardThumbnailAsync()
}
if (thumbnailData is not null && thumbnailData.Length > 0)
{
- Thumbnail = await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(Constants.Widgets.WidgetIconSize));
+ Thumbnail = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(Constants.Widgets.WidgetIconSize));
}
}
}
diff --git a/src/Files.App/Utils/Cloud/CloudDrivesManager.cs b/src/Files.App/Utils/Cloud/CloudDrivesManager.cs
index c25edca9c208..7953e17fa479 100644
--- a/src/Files.App/Utils/Cloud/CloudDrivesManager.cs
+++ b/src/Files.App/Utils/Cloud/CloudDrivesManager.cs
@@ -49,7 +49,7 @@ public async Task UpdateDrivesAsync()
{
cloudProviderItem.Root = await StorageFolder.GetFolderFromPathAsync(cloudProviderItem.Path);
- _ = App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => cloudProviderItem.UpdatePropertiesAsync());
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => cloudProviderItem.UpdatePropertiesAsync());
}
catch (Exception ex)
{
@@ -69,7 +69,7 @@ public async Task UpdateDrivesAsync()
{
cloudProviderItem.IconData = iconData;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async ()
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async ()
=> cloudProviderItem.Icon = await iconData.ToBitmapAsync());
}
diff --git a/src/Files.App/Utils/FilesystemOperations/Helpers/FilesystemHelpers.cs b/src/Files.App/Utils/FilesystemOperations/Helpers/FilesystemHelpers.cs
index 27ab99ae6e05..b15bb17e6217 100644
--- a/src/Files.App/Utils/FilesystemOperations/Helpers/FilesystemHelpers.cs
+++ b/src/Files.App/Utils/FilesystemOperations/Helpers/FilesystemHelpers.cs
@@ -1,11 +1,8 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using Files.App.Utils.FilesystemHistory;
-using Files.App.Utils.StorageItems;
-using Files.Core.Services;
-using Files.Core.ViewModels.Dialogs.FileSystemDialog;
using Files.Core.Storage;
+using Files.Core.Storage.Extensions;
using Files.Shared.Services;
using Microsoft.Extensions.Logging;
using System.IO;
@@ -673,7 +670,7 @@ public static bool IsValidForFilename(string name)
// Same item names in both directories
if (StorageHelpers.Exists(item.dest) ||
(FtpHelpers.IsFtpPath(item.dest) &&
- await Ioc.Default.GetRequiredService().FileExistsAsync(item.dest)))
+ await Ioc.Default.GetRequiredService().TryGetFileAsync(item.dest) is not null))
{
(incomingItems[item.index] as FileSystemDialogConflictItemViewModel)!.ConflictResolveOption = FileNameConflictResolveOptionType.GenerateNewName;
conflictingItems.Add(incomingItems.ElementAt(item.index));
diff --git a/src/Files.App/Utils/FilesystemOperations/ShellFilesystemOperations.cs b/src/Files.App/Utils/FilesystemOperations/ShellFilesystemOperations.cs
index 32c48535f509..f1024886ee6b 100644
--- a/src/Files.App/Utils/FilesystemOperations/ShellFilesystemOperations.cs
+++ b/src/Files.App/Utils/FilesystemOperations/ShellFilesystemOperations.cs
@@ -70,7 +70,7 @@ public async Task CopyItemsAsync(IList so
if (sourceRename.Any())
{
- var resultItem = await FileOperationsHelpers.CopyItemAsync(sourceRename.Select(s => s.Path).ToArray(), destinationRename.ToArray(), false, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var resultItem = await FileOperationsHelpers.CopyItemAsync(sourceRename.Select(s => s.Path).ToArray(), destinationRename.ToArray(), false, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
result &= (FilesystemResult)resultItem.Item1;
@@ -79,7 +79,7 @@ public async Task CopyItemsAsync(IList so
if (sourceReplace.Any())
{
- var resultItem = await FileOperationsHelpers.CopyItemAsync(sourceReplace.Select(s => s.Path).ToArray(), destinationReplace.ToArray(), true, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var resultItem = await FileOperationsHelpers.CopyItemAsync(sourceReplace.Select(s => s.Path).ToArray(), destinationReplace.ToArray(), true, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
result &= (FilesystemResult)resultItem.Item1;
@@ -358,7 +358,7 @@ public async Task DeleteItemsAsync(IList
var operationID = Guid.NewGuid().ToString();
using var r = cancellationToken.Register(CancelOperation, operationID, false);
- var (success, response) = await FileOperationsHelpers.DeleteItemAsync(deleteFilePaths.ToArray(), permanently, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var (success, response) = await FileOperationsHelpers.DeleteItemAsync(deleteFilePaths.ToArray(), permanently, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
var result = (FilesystemResult)success;
var deleteResult = new ShellOperationResult();
@@ -474,7 +474,7 @@ public async Task MoveItemsAsync(IList so
if (sourceRename.Any())
{
- var (status, response) = await FileOperationsHelpers.MoveItemAsync(sourceRename.Select(s => s.Path).ToArray(), destinationRename.ToArray(), false, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var (status, response) = await FileOperationsHelpers.MoveItemAsync(sourceRename.Select(s => s.Path).ToArray(), destinationRename.ToArray(), false, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
result &= (FilesystemResult)status;
moveResult.Items.AddRange(response?.Final ?? Enumerable.Empty());
@@ -482,7 +482,7 @@ public async Task MoveItemsAsync(IList so
if (sourceReplace.Any())
{
- var (status, response) = await FileOperationsHelpers.MoveItemAsync(sourceReplace.Select(s => s.Path).ToArray(), destinationReplace.ToArray(), true, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var (status, response) = await FileOperationsHelpers.MoveItemAsync(sourceReplace.Select(s => s.Path).ToArray(), destinationReplace.ToArray(), true, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
result &= (FilesystemResult)status;
moveResult.Items.AddRange(response?.Final ?? Enumerable.Empty());
@@ -709,7 +709,7 @@ public async Task RestoreItemsFromTrashAsync(IList s.Path).ToArray(), destination.ToArray(), false, NativeWinApiHelper.CoreWindowHandle.ToInt64(), progress, operationID);
+ var (status, response) = await FileOperationsHelpers.MoveItemAsync(source.Select(s => s.Path).ToArray(), destination.ToArray(), false, MainWindow.Instance.WindowHandle.ToInt64(), progress, operationID);
var result = (FilesystemResult)status;
moveResult.Items.AddRange(response?.Final ?? Enumerable.Empty());
diff --git a/src/Files.App/Utils/Git/GitHelpers.cs b/src/Files.App/Utils/Git/GitHelpers.cs
index 2a446bcda42e..4f99dce93d14 100644
--- a/src/Files.App/Utils/Git/GitHelpers.cs
+++ b/src/Files.App/Utils/Git/GitHelpers.cs
@@ -30,6 +30,8 @@ internal static class GitHelpers
private static readonly IDialogService _dialogService = Ioc.Default.GetRequiredService();
+ private static readonly IApplicationService _applicationService = Ioc.Default.GetRequiredService();
+
private static readonly FetchOptions _fetchOptions = new()
{
Prune = true
@@ -37,8 +39,7 @@ internal static class GitHelpers
private static readonly PullOptions _pullOptions = new();
- private static readonly string _clientId =
- EnvHelpers.GetAppEnvironmentAndLogo().Item1 is AppEnvironment.Store or AppEnvironment.Stable or AppEnvironment.Preview
+ private static readonly string _clientId = _applicationService.Environment is AppEnvironment.Store or AppEnvironment.Stable or AppEnvironment.Preview
? CLIENT_ID_SECRET
: string.Empty;
@@ -266,7 +267,7 @@ public static void FetchOrigin(string? repositoryPath)
_logger.LogWarning(ex.Message);
}
- App.Window.DispatcherQueue.TryEnqueue(() =>
+ MainWindow.Instance.DispatcherQueue.TryEnqueue(() =>
{
IsExecutingGitAction = false;
GitFetchCompleted?.Invoke(null, EventArgs.Empty);
diff --git a/src/Files.App/Utils/QuickAccessManager.cs b/src/Files.App/Utils/QuickAccessManager.cs
index ad983579026b..7bbe19ffc5a8 100644
--- a/src/Files.App/Utils/QuickAccessManager.cs
+++ b/src/Files.App/Utils/QuickAccessManager.cs
@@ -1,15 +1,9 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using CommunityToolkit.Mvvm.DependencyInjection;
-using CommunityToolkit.WinUI.Helpers;
-using Files.App.Data.Models;
-using Files.App.Helpers;
using Files.App.Services;
using Files.App.UserControls.Widgets;
-using System;
using System.IO;
-using System.Threading.Tasks;
namespace Files.App.Utils
{
@@ -21,14 +15,15 @@ public sealed class QuickAccessManager
public EventHandler? UpdateQuickAccessWidget;
- public IQuickAccessService QuickAccessService { get; } = Ioc.Default.GetRequiredService();
+ public IQuickAccessService QuickAccessService;
public SidebarPinnedModel Model;
public QuickAccessManager()
{
+ QuickAccessService = Ioc.Default.GetRequiredService();
Model = new();
Initialize();
- }
+ }
public void Initialize()
{
@@ -50,8 +45,8 @@ public async Task InitializeAsync()
{
PinnedItemsModified += Model.LoadAsync;
- if (!Model.FavoriteItems.Contains(Constants.UserEnvironmentPaths.RecycleBinPath) && SystemInformation.Instance.IsFirstRun)
- await QuickAccessService.PinToSidebar(Constants.UserEnvironmentPaths.RecycleBinPath);
+ //if (!Model.FavoriteItems.Contains(Constants.UserEnvironmentPaths.RecycleBinPath) && SystemInformation.Instance.IsFirstRun)
+ // await QuickAccessService.PinToSidebar(Constants.UserEnvironmentPaths.RecycleBinPath);
await Model.LoadAsync();
}
diff --git a/src/Files.App/Utils/Search/FolderSearch.cs b/src/Files.App/Utils/Search/FolderSearch.cs
index 08b50413bc34..ab9843846031 100644
--- a/src/Files.App/Utils/Search/FolderSearch.cs
+++ b/src/Files.App/Utils/Search/FolderSearch.cs
@@ -404,7 +404,7 @@ private ListedItem GetListedItemAsync(string itemPath, WIN32_FIND_DATA findData)
{
if (t.IsCompletedSuccessfully && t.Result is not null)
{
- _ = FilesystemTasks.Wrap(() => App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ _ = FilesystemTasks.Wrap(() => MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
listedItem.FileImage = await t.Result.ToBitmapAsync();
}, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low));
diff --git a/src/Files.App/ViewModels/Dialogs/CreateShortcutDialogViewModel.cs b/src/Files.App/ViewModels/Dialogs/CreateShortcutDialogViewModel.cs
index f0416e7192b6..efafa2cc96f4 100644
--- a/src/Files.App/ViewModels/Dialogs/CreateShortcutDialogViewModel.cs
+++ b/src/Files.App/ViewModels/Dialogs/CreateShortcutDialogViewModel.cs
@@ -100,7 +100,7 @@ private async Task SelectDestination()
private FolderPicker InitializeWithWindow(FolderPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/ViewModels/Dialogs/DecompressArchiveDialogViewModel.cs b/src/Files.App/ViewModels/Dialogs/DecompressArchiveDialogViewModel.cs
index 50b43acf1ac9..4b8a8ba03bb4 100644
--- a/src/Files.App/ViewModels/Dialogs/DecompressArchiveDialogViewModel.cs
+++ b/src/Files.App/ViewModels/Dialogs/DecompressArchiveDialogViewModel.cs
@@ -71,7 +71,7 @@ private async Task SelectDestination()
// WINUI3
private FolderPicker InitializeWithWindow(FolderPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/ViewModels/MainPageViewModel.cs b/src/Files.App/ViewModels/MainPageViewModel.cs
index 12b1dfed9ee4..86626e68b187 100644
--- a/src/Files.App/ViewModels/MainPageViewModel.cs
+++ b/src/Files.App/ViewModels/MainPageViewModel.cs
@@ -160,7 +160,7 @@ public async Task UpdateInstanceProperties(object navigationArg)
windowTitle = $"{windowTitle} ({AppInstances.Count})";
if (navigationArg == SelectedTabItem?.TabItemArguments?.NavigationArg)
- App.GetAppWindow(App.Window).Title = $"{windowTitle} - Files";
+ MainWindow.Instance.AppWindow.Title = $"{windowTitle} - Files";
}
public async Task UpdateTabInfo(TabItem tabItem, object navigationArg)
diff --git a/src/Files.App/ViewModels/Previews/BasePreviewModel.cs b/src/Files.App/ViewModels/Previews/BasePreviewModel.cs
index bc804e38dc72..e908434e1dfc 100644
--- a/src/Files.App/ViewModels/Previews/BasePreviewModel.cs
+++ b/src/Files.App/ViewModels/Previews/BasePreviewModel.cs
@@ -90,11 +90,11 @@ public async virtual Task> LoadPreviewAndDetailsAsync()
iconData ??= await FileThumbnailHelper.LoadIconWithoutOverlayAsync(Item.ItemPath, 256);
if (iconData is not null)
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () => FileImage = await iconData.ToBitmapAsync());
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () => FileImage = await iconData.ToBitmapAsync());
}
else
{
- FileImage ??= await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() => new BitmapImage());
+ FileImage ??= await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => new BitmapImage());
}
return new List();
diff --git a/src/Files.App/ViewModels/Previews/ImagePreviewViewModel.cs b/src/Files.App/ViewModels/Previews/ImagePreviewViewModel.cs
index 7bfaeadbfaba..7759b44c3d27 100644
--- a/src/Files.App/ViewModels/Previews/ImagePreviewViewModel.cs
+++ b/src/Files.App/ViewModels/Previews/ImagePreviewViewModel.cs
@@ -32,7 +32,7 @@ public override async Task> LoadPreviewAndDetailsAsync()
{
using IRandomAccessStream stream = await Item.ItemFile.OpenAsync(FileAccessMode.Read);
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
BitmapImage bitmap = new();
await bitmap.SetSourceAsync(stream);
diff --git a/src/Files.App/ViewModels/Previews/PDFPreviewViewModel.cs b/src/Files.App/ViewModels/Previews/PDFPreviewViewModel.cs
index c23b08f97a41..6aa749c07df6 100644
--- a/src/Files.App/ViewModels/Previews/PDFPreviewViewModel.cs
+++ b/src/Files.App/ViewModels/Previews/PDFPreviewViewModel.cs
@@ -88,7 +88,7 @@ private async Task LoadPagesAsync(PdfDocument pdf)
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
using SoftwareBitmap sw = await decoder.GetSoftwareBitmapAsync();
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
BitmapImage src = new();
PageViewModel pageData = new()
diff --git a/src/Files.App/ViewModels/Properties/CustomizationViewModel.cs b/src/Files.App/ViewModels/Properties/CustomizationViewModel.cs
index a04de662b473..c46d3c599764 100644
--- a/src/Files.App/ViewModels/Properties/CustomizationViewModel.cs
+++ b/src/Files.App/ViewModels/Properties/CustomizationViewModel.cs
@@ -125,7 +125,7 @@ public async Task UpdateIcon()
if (!result)
return false;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
_appInstance?.FilesystemViewModel?.RefreshItems(null);
});
diff --git a/src/Files.App/ViewModels/Properties/HashesViewModel.cs b/src/Files.App/ViewModels/Properties/HashesViewModel.cs
index a24c959ca1a5..b965a4eb86e1 100644
--- a/src/Files.App/ViewModels/Properties/HashesViewModel.cs
+++ b/src/Files.App/ViewModels/Properties/HashesViewModel.cs
@@ -84,7 +84,7 @@ private void ToggleIsEnabled(string? algorithm)
{
hashInfoItem.IsCalculating = true;
- App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
try
{
diff --git a/src/Files.App/ViewModels/Properties/Items/FileProperties.cs b/src/Files.App/ViewModels/Properties/Items/FileProperties.cs
index 82a70bfe14ca..cbc83be4ffa0 100644
--- a/src/Files.App/ViewModels/Properties/Items/FileProperties.cs
+++ b/src/Files.App/ViewModels/Properties/Items/FileProperties.cs
@@ -78,7 +78,7 @@ public override void GetBaseProperties()
}
else
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(
() => NavigationHelpers.OpenPathInNewTab(Path.GetDirectoryName(ViewModel.ShortcutItemPath)));
}
},
diff --git a/src/Files.App/ViewModels/Properties/Items/FolderProperties.cs b/src/Files.App/ViewModels/Properties/Items/FolderProperties.cs
index 30850ae8dddf..ed0859014d8e 100644
--- a/src/Files.App/ViewModels/Properties/Items/FolderProperties.cs
+++ b/src/Files.App/ViewModels/Properties/Items/FolderProperties.cs
@@ -61,7 +61,7 @@ public override void GetBaseProperties()
ViewModel.ShortcutItemArgumentsVisibility = false;
ViewModel.ShortcutItemOpenLinkCommand = new RelayCommand(async () =>
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(
() => NavigationHelpers.OpenPathInNewTab(Path.GetDirectoryName(Environment.ExpandEnvironmentVariables(ViewModel.ShortcutItemPath))));
},
() =>
diff --git a/src/Files.App/ViewModels/Properties/SecurityAdvancedViewModel.cs b/src/Files.App/ViewModels/Properties/SecurityAdvancedViewModel.cs
index 3ef475538864..8d4ae7deac36 100644
--- a/src/Files.App/ViewModels/Properties/SecurityAdvancedViewModel.cs
+++ b/src/Files.App/ViewModels/Properties/SecurityAdvancedViewModel.cs
@@ -202,7 +202,7 @@ private async Task ExecuteChangeOwnerCommand()
if (string.IsNullOrEmpty(sid))
return;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
// Set owner
FileSecurityHelpers.SetOwner(_path, sid);
@@ -219,7 +219,7 @@ private async Task ExecuteAddAccessControlEntryCommand()
if (string.IsNullOrEmpty(sid))
return;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
// Run Win32API
var win32Result = FileSecurityHelpers.AddAccessControlEntry(_path, sid);
@@ -235,7 +235,7 @@ private async Task ExecuteRemoveAccessControlEntryCommand()
if (SelectedAccessControlEntry is null)
return;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
// Get index of the ACE
var index = AccessControlList.AccessControlEntries.IndexOf(SelectedAccessControlEntry);
diff --git a/src/Files.App/ViewModels/Properties/SecurityViewModel.cs b/src/Files.App/ViewModels/Properties/SecurityViewModel.cs
index 54bfdc3891ff..a3ac248f4e0b 100644
--- a/src/Files.App/ViewModels/Properties/SecurityViewModel.cs
+++ b/src/Files.App/ViewModels/Properties/SecurityViewModel.cs
@@ -117,7 +117,7 @@ private async Task ExecuteAddAccessControlEntryCommand()
if (string.IsNullOrEmpty(sid))
return;
- await App.Window.DispatcherQueue.EnqueueAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueAsync(() =>
{
// Run Win32API
var win32Result = FileSecurityHelpers.AddAccessControlEntry(_path, sid);
@@ -130,7 +130,7 @@ await App.Window.DispatcherQueue.EnqueueAsync(() =>
private async Task ExecuteRemoveAccessControlEntryCommand()
{
- await App.Window.DispatcherQueue.EnqueueAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueAsync(() =>
{
// Get index of the ACE
var index = AccessControlList.AccessControlEntries.IndexOf(SelectedAccessControlEntry);
diff --git a/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs b/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs
index 708a52ee05ec..5059e6541178 100644
--- a/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs
+++ b/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs
@@ -199,9 +199,11 @@ private async Task ImportSettings()
private async Task ExportSettings()
{
+ var applicationService = Ioc.Default.GetRequiredService();
+
FileSavePicker filePicker = InitializeWithWindow(new FileSavePicker());
filePicker.FileTypeChoices.Add("Zip File", new[] { ".zip" });
- filePicker.SuggestedFileName = $"Files_{App.AppVersion}";
+ filePicker.SuggestedFileName = $"Files_{applicationService.AppVersion}";
StorageFile file = await filePicker.PickSaveFileAsync();
if (file is not null)
@@ -270,14 +272,14 @@ public bool IsSetAsOpenFileDialog
private FileSavePicker InitializeWithWindow(FileSavePicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
private FileOpenPicker InitializeWithWindow(FileOpenPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/ViewModels/Settings/GeneralViewModel.cs b/src/Files.App/ViewModels/Settings/GeneralViewModel.cs
index 1ec657e60805..755acf11d3af 100644
--- a/src/Files.App/ViewModels/Settings/GeneralViewModel.cs
+++ b/src/Files.App/ViewModels/Settings/GeneralViewModel.cs
@@ -334,7 +334,7 @@ private async Task ChangePage()
// WINUI3
private FolderPicker InitializeWithWindow(FolderPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs b/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs
index 30f5688b7b95..68e2282197d5 100644
--- a/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs
+++ b/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs
@@ -477,7 +477,7 @@ public async Task PathBoxItem_Tapped(object sender, TappedRoutedEventArgs e)
if (pointerRoutedEventArgs is not null)
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await mainPageViewModel.AddNewTabByPathAsync(typeof(PaneHolderPage), itemTappedPath);
}, DispatcherQueuePriority.Low);
@@ -516,7 +516,7 @@ public void UpdateAdditionalActions()
OnPropertyChanged(nameof(HasAdditionalAction));
}
- private AddressToolbar? AddressToolbar => (App.Window.Content as Frame)?.FindDescendant();
+ private AddressToolbar? AddressToolbar => (MainWindow.Instance.Content as Frame)?.FindDescendant();
public void CloseSearchBox()
{
diff --git a/src/Files.App/ViewModels/Widgets/FileTagsItemViewModel.cs b/src/Files.App/ViewModels/Widgets/FileTagsItemViewModel.cs
index 0d5ab72b1d9c..5199b196e0b8 100644
--- a/src/Files.App/ViewModels/Widgets/FileTagsItemViewModel.cs
+++ b/src/Files.App/ViewModels/Widgets/FileTagsItemViewModel.cs
@@ -1,15 +1,15 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using Files.Core.Storage.Extensions;
-using Files.Core.Storage.LocatableStorage;
using Files.App.UserControls.Widgets;
+using Files.Core.Storage;
+using Files.Core.Storage.Extensions;
namespace Files.App.ViewModels.Widgets
{
public sealed partial class FileTagsItemViewModel : WidgetCardItem
{
- private readonly ILocatableStorable _associatedStorable;
+ private readonly IStorable _associatedStorable;
// A workaround for lack of MVVM-compliant navigation support.
// This workaround must be kept until further refactor of navigation code is completed.
@@ -28,14 +28,14 @@ public override string Path
set => SetProperty(ref path, value);
}
- public bool IsFolder => _associatedStorable is ILocatableFolder;
+ public bool IsFolder => _associatedStorable is IFolder;
- public FileTagsItemViewModel(ILocatableStorable associatedStorable, Func openAction, IImageModel? icon)
+ public FileTagsItemViewModel(IStorable associatedStorable, Func openAction, IImageModel? icon)
{
_associatedStorable = associatedStorable;
_openAction = openAction;
_Icon = icon;
- _Name = PathHelpers.FormatName(associatedStorable.Path);
+ _Name = PathHelpers.FormatName(associatedStorable.Id);
Path = associatedStorable.TryGetPath();
Item = this;
}
@@ -43,7 +43,7 @@ public FileTagsItemViewModel(ILocatableStorable associatedStorable, Func (App.Window.Content as Frame)?.FindDescendant();
+ => (MainWindow.Instance.Content as Frame)?.FindDescendant();
private CollectionViewSource collectionViewSource = new()
{
@@ -733,7 +733,7 @@ private async Task AddShellMenuItemsAsync(List s
var overflowItems = ItemModelListToContextFlyoutHelper.GetMenuFlyoutItemsFromModel(overflowShellMenuItems);
var mainItems = ItemModelListToContextFlyoutHelper.GetAppBarButtonsFromModelIgnorePrimary(mainShellMenuItems);
- var openedPopups = Microsoft.UI.Xaml.Media.VisualTreeHelper.GetOpenPopups(App.Window);
+ var openedPopups = Microsoft.UI.Xaml.Media.VisualTreeHelper.GetOpenPopups(MainWindow.Instance);
var secondaryMenu = openedPopups.FirstOrDefault(popup => popup.Name == "OverflowPopup");
var itemsControl = secondaryMenu?.Child.FindDescendant();
@@ -741,11 +741,11 @@ private async Task AddShellMenuItemsAsync(List s
{
contextMenuFlyout.SetValue(ContextMenuExtensions.ItemsControlProperty, itemsControl);
- var ttv = secondaryMenu.TransformToVisual(App.Window.Content);
+ var ttv = secondaryMenu.TransformToVisual(MainWindow.Instance.Content);
var cMenuPos = ttv.TransformPoint(new Point(0, 0));
var requiredHeight = contextMenuFlyout.SecondaryCommands.Concat(mainItems).Where(x => x is not AppBarSeparator).Count() * Constants.UI.ContextMenuSecondaryItemsHeight;
- var availableHeight = App.Window.Bounds.Height - cMenuPos.Y - Constants.UI.ContextMenuPrimaryItemsHeight;
+ var availableHeight = MainWindow.Instance.Bounds.Height - cMenuPos.Y - Constants.UI.ContextMenuPrimaryItemsHeight;
// Set menu max height to current height (Avoid menu repositioning)
if (requiredHeight > availableHeight)
@@ -1390,7 +1390,7 @@ protected void UpdatePreviewPaneSelection(List? value)
// Check if the preview pane is open before updating the model
if (PreviewPaneViewModel.IsEnabled)
{
- var isPaneEnabled = ((App.Window.Content as Frame)?.Content as MainPage)?.ShouldPreviewPaneBeActive ?? false;
+ var isPaneEnabled = ((MainWindow.Instance.Content as Frame)?.Content as MainPage)?.ShouldPreviewPaneBeActive ?? false;
if (isPaneEnabled)
_ = PreviewPaneViewModel.UpdateSelectedItemPreview();
}
diff --git a/src/Files.App/Views/MainPage.xaml.cs b/src/Files.App/Views/MainPage.xaml.cs
index b46943b4c0bc..768dac88d10b 100644
--- a/src/Files.App/Views/MainPage.xaml.cs
+++ b/src/Files.App/Views/MainPage.xaml.cs
@@ -82,7 +82,7 @@ private async Task PromptForReview()
try
{
var storeContext = StoreContext.GetDefault();
- InitializeWithWindow.Initialize(storeContext, App.WindowHandle);
+ InitializeWithWindow.Initialize(storeContext, MainWindow.Instance.WindowHandle);
var storeRateAndReviewResult = await storeContext.RequestRateAndReviewAppAsync();
App.Logger.LogInformation($"STORE: review request status: {storeRateAndReviewResult.Status}");
@@ -97,7 +97,7 @@ private async Task PromptForReview()
private ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
{
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
- contentDialog.XamlRoot = App.Window.Content.XamlRoot;
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
return contentDialog;
}
@@ -127,7 +127,7 @@ private void HorizontalMultitaskingControl_Loaded(object sender, RoutedEventArgs
private void SetRectDragRegion()
{
DragZoneHelper.SetDragZones(
- App.Window,
+ MainWindow.Instance,
dragZoneLeftIndent: (int)(TabControl.ActualWidth + TabControl.Margin.Left - TabControl.DragArea.ActualWidth));
}
@@ -494,7 +494,7 @@ public bool ShouldPreviewPaneBeDisplayed
{
var isHomePage = !(SidebarAdaptiveViewModel.PaneHolder?.ActivePane?.InstanceViewModel?.IsPageTypeNotHome ?? false);
var isMultiPane = SidebarAdaptiveViewModel.PaneHolder?.IsMultiPaneActive ?? false;
- var isBigEnough = App.Window.Bounds.Width > 450 && App.Window.Bounds.Height > 450 || RootGrid.ActualWidth > 700 && App.Window.Bounds.Height > 360;
+ var isBigEnough = MainWindow.Instance.Bounds.Width > 450 && MainWindow.Instance.Bounds.Height > 450 || RootGrid.ActualWidth > 700 && MainWindow.Instance.Bounds.Height > 360;
var isEnabled = (!isHomePage || isMultiPane) && isBigEnough;
return isEnabled;
diff --git a/src/Files.App/Views/PaneHolderPage.xaml.cs b/src/Files.App/Views/PaneHolderPage.xaml.cs
index 5156163eb822..52867dbd0d96 100644
--- a/src/Files.App/Views/PaneHolderPage.xaml.cs
+++ b/src/Files.App/Views/PaneHolderPage.xaml.cs
@@ -46,7 +46,7 @@ public TabItemArguments TabItemArguments
}
}
- private bool _WindowIsCompact = App.Window.Bounds.Width <= 750;
+ private bool _WindowIsCompact = MainWindow.Instance.Bounds.Width <= 750;
public bool WindowIsCompact
{
get => _WindowIsCompact;
@@ -78,7 +78,7 @@ public bool IsMultiPaneActive
=> IsRightPaneVisible;
public bool IsMultiPaneEnabled
- => !(App.Window.Bounds.Width <= 750);
+ => !(MainWindow.Instance.Bounds.Width <= 750);
private NavigationParams _NavParamsLeft;
public NavigationParams NavParamsLeft
@@ -199,7 +199,7 @@ public PaneHolderPage()
UserSettingsService = Ioc.Default.GetRequiredService();
- App.Window.SizeChanged += Current_SizeChanged;
+ MainWindow.Instance.SizeChanged += Current_SizeChanged;
ActivePane = PaneLeft;
IsRightPaneVisible = IsMultiPaneEnabled && UserSettingsService.GeneralSettingsService.AlwaysOpenDualPaneInNewTab;
@@ -208,7 +208,7 @@ public PaneHolderPage()
private void Current_SizeChanged(object sender, WindowSizeChangedEventArgs e)
{
- WindowIsCompact = App.Window.Bounds.Width <= 750;
+ WindowIsCompact = MainWindow.Instance.Bounds.Width <= 750;
}
protected override void OnNavigatedTo(NavigationEventArgs eventArgs)
@@ -355,7 +355,7 @@ private async void Pane_GotFocus(object sender, RoutedEventArgs e)
public void Dispose()
{
- App.Window.SizeChanged -= Current_SizeChanged;
+ MainWindow.Instance.SizeChanged -= Current_SizeChanged;
PaneLeft?.Dispose();
PaneRight?.Dispose();
PaneResizer.DoubleTapped -= PaneResizer_OnDoubleTapped;
diff --git a/src/Files.App/Views/Properties/GeneralPage.xaml.cs b/src/Files.App/Views/Properties/GeneralPage.xaml.cs
index a8aafc908071..d1ee198bb351 100644
--- a/src/Files.App/Views/Properties/GeneralPage.xaml.cs
+++ b/src/Files.App/Views/Properties/GeneralPage.xaml.cs
@@ -86,7 +86,7 @@ bool SaveDrive(DriveItem drive)
newName = letterRegex.Replace(newName, string.Empty); // Remove "(C:)" from the new label
Win32API.SetVolumeLabel(drive.Path, newName);
- _ = App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await drive.UpdateLabelAsync();
await fsVM.SetWorkingDirectoryAsync(drive.Path);
@@ -107,7 +107,7 @@ async Task SaveLibraryAsync(LibraryItem library)
if (renamed is ReturnResult.Success)
{
var newPath = Path.Combine(Path.GetDirectoryName(library.ItemPath)!, newName);
- _ = App.Window.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
+ _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await fsVM.SetWorkingDirectoryAsync(newPath);
});
@@ -125,7 +125,7 @@ async Task SaveCombinedAsync(IList fileOrFolders)
{
foreach (var fileOrFolder in fileOrFolders)
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
UIFilesystemHelpers.SetHiddenAttributeItem(fileOrFolder, ViewModel.IsHidden, itemMM)
);
}
@@ -139,7 +139,7 @@ async Task SaveBaseAsync(ListedItem item)
var itemMM = AppInstance?.SlimContentPage?.ItemManipulationModel;
if (itemMM is not null) // null on homepage
{
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
UIFilesystemHelpers.SetHiddenAttributeItem(item, ViewModel.IsHidden, itemMM)
);
}
@@ -147,7 +147,7 @@ await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
if (!GetNewName(out var newName))
return true;
- return await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ return await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
UIFilesystemHelpers.RenameFileItemAsync(item, ViewModel.ItemName, AppInstance, false)
);
}
diff --git a/src/Files.App/Views/Properties/LibraryPage.xaml.cs b/src/Files.App/Views/Properties/LibraryPage.xaml.cs
index 92dba43938df..b18a5f2bb7ae 100644
--- a/src/Files.App/Views/Properties/LibraryPage.xaml.cs
+++ b/src/Files.App/Views/Properties/LibraryPage.xaml.cs
@@ -119,7 +119,7 @@ private async Task AddLocation()
// WINUI3
private FolderPicker InitializeWithWindow(FolderPicker obj)
{
- WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
+ WinRT.Interop.InitializeWithWindow.Initialize(obj, MainWindow.Instance.WindowHandle);
return obj;
}
diff --git a/src/Files.App/Views/Properties/ShortcutPage.xaml.cs b/src/Files.App/Views/Properties/ShortcutPage.xaml.cs
index c3dde60d92ad..d826b712cead 100644
--- a/src/Files.App/Views/Properties/ShortcutPage.xaml.cs
+++ b/src/Files.App/Views/Properties/ShortcutPage.xaml.cs
@@ -29,7 +29,7 @@ public override async Task SaveChangesAsync()
if (shortcutItem is null)
return true;
- await App.Window.DispatcherQueue.EnqueueOrInvokeAsync(() =>
+ await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() =>
UIFilesystemHelpers.UpdateShortcutItemProperties(shortcutItem,
ViewModel.ShortcutItemPath,
ViewModel.ShortcutItemArguments,
diff --git a/src/Files.App/Views/Shells/BaseShellPage.cs b/src/Files.App/Views/Shells/BaseShellPage.cs
index dc37947b3cb6..d69894115e68 100644
--- a/src/Files.App/Views/Shells/BaseShellPage.cs
+++ b/src/Files.App/Views/Shells/BaseShellPage.cs
@@ -690,7 +690,7 @@ protected void SelectSidebarItemFromPath(Type incomingSourcePageType = null)
protected void SetLoadingIndicatorForTabs(bool isLoading)
{
- var multitaskingControls = ((App.Window.Content as Frame).Content as MainPage).ViewModel.MultitaskingControls;
+ var multitaskingControls = ((MainWindow.Instance.Content as Frame).Content as MainPage).ViewModel.MultitaskingControls;
foreach (var x in multitaskingControls)
x.SetLoadingIndicatorStatus(x.Items.FirstOrDefault(x => x.Control.TabItemContent == PaneHolder), isLoading);
@@ -700,7 +700,7 @@ protected void SetLoadingIndicatorForTabs(bool isLoading)
protected static ContentDialog SetContentDialogRoot(ContentDialog contentDialog)
{
if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
- contentDialog.XamlRoot = App.Window.Content.XamlRoot;
+ contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
return contentDialog;
}
diff --git a/src/Files.Core.Storage/DirectStorage/IDirectCopy.cs b/src/Files.Core.Storage/DirectStorage/IDirectCopy.cs
new file mode 100644
index 000000000000..b03bf7974834
--- /dev/null
+++ b/src/Files.Core.Storage/DirectStorage/IDirectCopy.cs
@@ -0,0 +1,18 @@
+using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Files.Core.Storage.DirectStorage
+{
+ ///
+ /// Provides direct copy operation of storage objects.
+ ///
+ public interface IDirectCopy : IModifiableFolder
+ {
+ ///
+ /// Creates a copy of the provided storable item in this folder.
+ ///
+ Task CreateCopyOfAsync(INestedStorable itemToCopy, bool overwrite = default, CancellationToken cancellationToken = default);
+ }
+}
diff --git a/src/Files.Core.Storage/DirectStorage/IDirectMove.cs b/src/Files.Core.Storage/DirectStorage/IDirectMove.cs
new file mode 100644
index 000000000000..074391439215
--- /dev/null
+++ b/src/Files.Core.Storage/DirectStorage/IDirectMove.cs
@@ -0,0 +1,18 @@
+using Files.Core.Storage.ModifiableStorage;
+using Files.Core.Storage.NestedStorage;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Files.Core.Storage.DirectStorage
+{
+ ///
+ /// Provides direct move operation of storage objects.
+ ///
+ public interface IDirectMove : IModifiableFolder
+ {
+ ///
+ /// Moves a storable item out of the provided folder, and into this folder. Returns the new item that resides in this folder.
+ ///
+ Task MoveFromAsync(INestedStorable itemToMove, IModifiableFolder source, bool overwrite = default, CancellationToken cancellationToken = default);
+ }
+}
diff --git a/src/Files.Core.Storage/Enums/CreationCollisionOption.cs b/src/Files.Core.Storage/Enums/CreationCollisionOption.cs
deleted file mode 100644
index 835e89236f79..000000000000
--- a/src/Files.Core.Storage/Enums/CreationCollisionOption.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2023 Files Community
-// Licensed under the MIT License. See the LICENSE.
-
-namespace Files.Core.Storage.Enums
-{
- public enum CreationCollisionOption : byte
- {
- GenerateUniqueName = 0,
- ReplaceExisting = 1,
- OpenIfExists = 2,
- FailIfExists = 3,
- }
-}
diff --git a/src/Files.Core.Storage/Enums/NameCollisionOption.cs b/src/Files.Core.Storage/Enums/NameCollisionOption.cs
deleted file mode 100644
index e349fc257be7..000000000000
--- a/src/Files.Core.Storage/Enums/NameCollisionOption.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2023 Files Community
-// Licensed under the MIT License. See the LICENSE.
-
-namespace Files.Core.Storage.Enums
-{
- public enum NameCollisionOption : byte
- {
- GenerateUniqueName = 0,
- ReplaceExisting = 1,
- FailIfExists = 2
- }
-}
diff --git a/src/Files.Core.Storage/ExtendableStorage/IFolderExtended.cs b/src/Files.Core.Storage/ExtendableStorage/IFolderExtended.cs
new file mode 100644
index 000000000000..05f06ed27caf
--- /dev/null
+++ b/src/Files.Core.Storage/ExtendableStorage/IFolderExtended.cs
@@ -0,0 +1,28 @@
+using Files.Core.Storage.NestedStorage;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Files.Core.Storage.ExtendableStorage
+{
+ ///