Skip to content

Commit 0b565ce

Browse files
authored
Disable Move operation on folders when using StorageFile APIs (#8960)
1 parent 73935b3 commit 0b565ce

File tree

3 files changed

+64
-34
lines changed

3 files changed

+64
-34
lines changed

src/Files.Uwp/Filesystem/FilesystemOperations/FilesystemOperations.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,13 @@ await DialogDisplayHelper.ShowDialogAsync(
392392

393393
if (fsResult)
394394
{
395-
var fsResultMove = await FilesystemTasks.Wrap(() => MoveDirectoryAsync((BaseStorageFolder)fsSourceFolder, (BaseStorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, collision.Convert(), true));
395+
// Moving folders using Storage API can result in data loss, copy instead
396+
//var fsResultMove = await FilesystemTasks.Wrap(() => MoveDirectoryAsync((BaseStorageFolder)fsSourceFolder, (BaseStorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, collision.Convert(), true));
397+
var fsResultMove = new FilesystemResult<BaseStorageFolder>(null, FileSystemStatusCode.Generic);
398+
if (await DialogDisplayHelper.ShowDialogAsync("ErrorDialogThisActionCannotBeDone".GetLocalized(), "ErrorDialogUnsupportedMoveOperation".GetLocalized(), "OK", "Cancel".GetLocalized()))
399+
{
400+
fsResultMove = await FilesystemTasks.Wrap(() => CloneDirectoryAsync((BaseStorageFolder)fsSourceFolder, (BaseStorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, collision.Convert()));
401+
}
396402

397403
if (fsResultMove == FileSystemStatusCode.AlreadyExists)
398404
{
@@ -749,8 +755,12 @@ public async Task<IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath so
749755

750756
if (fsResult)
751757
{
752-
fsResult = await FilesystemTasks.Wrap(() => MoveDirectoryAsync(sourceFolder.Result, destinationFolder.Result, Path.GetFileName(destination),
753-
CreationCollisionOption.FailIfExists, true));
758+
// Moving folders using Storage API can result in data loss, copy instead
759+
//fsResult = await FilesystemTasks.Wrap(() => MoveDirectoryAsync(sourceFolder.Result, destinationFolder.Result, Path.GetFileName(destination), CreationCollisionOption.FailIfExists, true));
760+
if (await DialogDisplayHelper.ShowDialogAsync("ErrorDialogThisActionCannotBeDone".GetLocalized(), "ErrorDialogUnsupportedMoveOperation".GetLocalized(), "OK", "Cancel".GetLocalized()))
761+
{
762+
fsResult = await FilesystemTasks.Wrap(() => CloneDirectoryAsync(sourceFolder.Result, destinationFolder.Result, Path.GetFileName(destination), CreationCollisionOption.FailIfExists));
763+
}
754764
// TODO: we could use here FilesystemHelpers with registerHistory false?
755765
}
756766
errorCode?.Report(fsResult);
@@ -825,6 +835,7 @@ private async static Task<BaseStorageFolder> CloneDirectoryAsync(BaseStorageFold
825835
return createdRoot;
826836
}
827837

838+
[Obsolete("Moving folders using Storage API can result in data loss. For example hidden folders will not be moved but the parent folder will be deleted at the end. If this happens on a drive without recycle bin StorageDeleteOption.Default results in a permanent delete.")]
828839
private static async Task<BaseStorageFolder> MoveDirectoryAsync(BaseStorageFolder sourceFolder, BaseStorageFolder destinationDirectory, string sourceRootName, CreationCollisionOption collision = CreationCollisionOption.FailIfExists, bool deleteSource = false)
829840
{
830841
BaseStorageFolder createdRoot = await destinationDirectory.CreateFolderAsync(sourceRootName, collision);

src/Files.Uwp/MultilingualResources/Files.it-IT.xlf

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,6 @@
242242
<source>Application</source>
243243
<target state="translated">Applicazione</target>
244244
</trans-unit>
245-
<trans-unit id="SystemTimeStye" translate="yes" xml:space="preserve">
246-
<source>System</source>
247-
<target state="translated">Sistema</target>
248-
</trans-unit>
249245
<trans-unit id="NewFolder" translate="yes" xml:space="preserve">
250246
<source>New Folder</source>
251247
<target state="translated">Nuova cartella</target>
@@ -3522,6 +3518,26 @@ Usiamo App Center per tenere traccia dell'utilizzo dell'app, trovare bug e risol
35223518
<source>File is in use</source>
35233519
<target state="translated">Il file è in uso</target>
35243520
</trans-unit>
3521+
<trans-unit id="SystemTimeStyle" translate="yes" xml:space="preserve">
3522+
<source>System</source>
3523+
<target state="new">System</target>
3524+
</trans-unit>
3525+
<trans-unit id="Universal" translate="yes" xml:space="preserve">
3526+
<source>Universal</source>
3527+
<target state="new">Universal</target>
3528+
</trans-unit>
3529+
<trans-unit id="DateFormatSample" translate="yes" xml:space="preserve">
3530+
<source>ex: {0}, {1}</source>
3531+
<target state="new">ex: {0}, {1}</target>
3532+
</trans-unit>
3533+
<trans-unit id="SettingsFilesAndFoldersShowThumbnails" translate="yes" xml:space="preserve">
3534+
<source>Show thumbnails</source>
3535+
<target state="new">Show thumbnails</target>
3536+
</trans-unit>
3537+
<trans-unit id="ErrorDialogUnsupportedMoveOperation" translate="yes" xml:space="preserve">
3538+
<source>Move operation is not supported in this context. Do you want to copy the items instead?</source>
3539+
<target state="translated">L'operazione di spostamento non è supportata in questo contesto. Vuoi copiare gli elementi?</target>
3540+
</trans-unit>
35253541
</group>
35263542
</body>
35273543
</file>

src/Files.Uwp/Strings/en-US/Resources.resw

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<root>
3-
<!--
4-
Microsoft ResX Schema
5-
3+
<!--
4+
Microsoft ResX Schema
5+
66
Version 2.0
7-
8-
The primary goals of this format is to allow a simple XML format
9-
that is mostly human readable. The generation and parsing of the
10-
various data types are done through the TypeConverter classes
7+
8+
The primary goals of this format is to allow a simple XML format
9+
that is mostly human readable. The generation and parsing of the
10+
various data types are done through the TypeConverter classes
1111
associated with the data types.
12-
12+
1313
Example:
14-
14+
1515
... ado.net/XML headers & schema ...
1616
<resheader name="resmimetype">text/microsoft-resx</resheader>
1717
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
2626
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
2727
<comment>This is a comment</comment>
2828
</data>
29-
30-
There are any number of "resheader" rows that contain simple
29+
30+
There are any number of "resheader" rows that contain simple
3131
name/value pairs.
32-
33-
Each data row contains a name, and value. The row also contains a
34-
type or mimetype. Type corresponds to a .NET class that support
35-
text/value conversion through the TypeConverter architecture.
36-
Classes that don't support this are serialized and stored with the
32+
33+
Each data row contains a name, and value. The row also contains a
34+
type or mimetype. Type corresponds to a .NET class that support
35+
text/value conversion through the TypeConverter architecture.
36+
Classes that don't support this are serialized and stored with the
3737
mimetype set.
38-
39-
The mimetype is used for serialized objects, and tells the
40-
ResXResourceReader how to depersist the object. This is currently not
38+
39+
The mimetype is used for serialized objects, and tells the
40+
ResXResourceReader how to depersist the object. This is currently not
4141
extensible. For a given mimetype the value must be set accordingly:
42-
43-
Note - application/x-microsoft.net.object.binary.base64 is the format
44-
that the ResXResourceWriter will generate, however the reader can
42+
43+
Note - application/x-microsoft.net.object.binary.base64 is the format
44+
that the ResXResourceWriter will generate, however the reader can
4545
read any of the formats listed below.
46-
46+
4747
mimetype: application/x-microsoft.net.object.binary.base64
48-
value : The object must be serialized with
48+
value : The object must be serialized with
4949
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
5050
: and then encoded with base64 encoding.
51-
51+
5252
mimetype: application/x-microsoft.net.object.soap.base64
53-
value : The object must be serialized with
53+
value : The object must be serialized with
5454
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
5555
: and then encoded with base64 encoding.
5656
5757
mimetype: application/x-microsoft.net.object.bytearray.base64
58-
value : The object must be serialized into a byte array
58+
value : The object must be serialized into a byte array
5959
: using a System.ComponentModel.TypeConverter
6060
: and then encoded with base64 encoding.
6161
-->
@@ -2759,4 +2759,7 @@ We use App Center to track which settings are being used, find bugs, and fix cra
27592759
<data name="SettingsFilesAndFoldersShowThumbnails" xml:space="preserve">
27602760
<value>Show thumbnails</value>
27612761
</data>
2762+
<data name="ErrorDialogUnsupportedMoveOperation" xml:space="preserve">
2763+
<value>Move operation is not supported in this context. Do you want to copy the items instead?</value>
2764+
</data>
27622765
</root>

0 commit comments

Comments
 (0)