Merge branch 'master' into spelling

This commit is contained in:
Clint Rutkas
2020-11-02 09:57:48 -08:00
committed by GitHub
245 changed files with 2177 additions and 1210 deletions

View File

@@ -69,6 +69,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.IO.Abstractions" Version="12.2.5" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">

View File

@@ -5,7 +5,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;

View File

@@ -170,6 +170,7 @@ namespace ImageResizer.Properties
var result = ((IDataErrorInfo)settings)["JpegQualityLevel"];
// Using InvariantCulture since this is used internally
Assert.Equal(
string.Format(CultureInfo.InvariantCulture, Resources.ValueMustBeBetween, 1, 100),
result);

View File

@@ -6,7 +6,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.IO.Abstractions;
using System.Windows.Media.Imaging;
using Xunit;
@@ -14,6 +14,8 @@ namespace ImageResizer.Test
{
internal static class AssertEx
{
private static readonly IFileSystem _fileSystem = new FileSystem();
public static void All<T>(IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
@@ -24,7 +26,7 @@ namespace ImageResizer.Test
public static void Image(string path, Action<BitmapDecoder> action)
{
using (var stream = File.OpenRead(path))
using (var stream = _fileSystem.File.OpenRead(path))
{
var image = BitmapDecoder.Create(
stream,

View File

@@ -28,6 +28,7 @@ namespace ImageResizer.Views
var timeRemaining = new TimeSpan(hours, minutes, seconds);
var converter = new TimeRemainingConverter();
// Using InvariantCulture since these are internal
var result = converter.Convert(
timeRemaining,
targetType: null,

View File

@@ -69,6 +69,9 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.IO.Abstractions">
<Version>12.2.5</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\interop\interop.vcxproj" />

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Threading;
using System.Threading.Tasks;
using ImageResizer.Properties;
@@ -14,6 +15,8 @@ namespace ImageResizer.Models
{
public class ResizeBatch
{
private readonly IFileSystem _fileSystem = new FileSystem();
public string DestinationDirectory { get; set; }
public ICollection<string> Files { get; } = new List<string>();
@@ -71,7 +74,7 @@ namespace ImageResizer.Models
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
errors.Add(new ResizeError { File = Path.GetFileName(file), Error = ex.Message });
errors.Add(new ResizeError { File = _fileSystem.Path.GetFileName(file), Error = ex.Message });
}
Interlocked.Increment(ref completed);

View File

@@ -5,6 +5,7 @@
using System;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Windows;
using System.Windows.Media;
@@ -12,11 +13,14 @@ using System.Windows.Media.Imaging;
using ImageResizer.Properties;
using ImageResizer.Utilities;
using Microsoft.VisualBasic.FileIO;
using FileSystem = Microsoft.VisualBasic.FileIO.FileSystem;
namespace ImageResizer.Models
{
internal class ResizeOperation
{
private readonly IFileSystem _fileSystem = new System.IO.Abstractions.FileSystem();
private readonly string _file;
private readonly string _destinationDirectory;
private readonly Settings _settings;
@@ -31,7 +35,7 @@ namespace ImageResizer.Models
public void Execute()
{
string path;
using (var inputStream = File.OpenRead(_file))
using (var inputStream = _fileSystem.File.OpenRead(_file))
{
var decoder = BitmapDecoder.Create(
inputStream,
@@ -87,8 +91,8 @@ namespace ImageResizer.Models
}
path = GetDestinationPath(encoder);
Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var outputStream = File.Open(path, FileMode.CreateNew, FileAccess.Write))
_fileSystem.Directory.CreateDirectory(_fileSystem.Path.GetDirectoryName(path));
using (var outputStream = _fileSystem.File.Open(path, FileMode.CreateNew, FileAccess.Write))
{
encoder.Save(outputStream);
}
@@ -96,13 +100,13 @@ namespace ImageResizer.Models
if (_settings.KeepDateModified)
{
File.SetLastWriteTimeUtc(path, File.GetLastWriteTimeUtc(_file));
_fileSystem.File.SetLastWriteTimeUtc(path, _fileSystem.File.GetLastWriteTimeUtc(_file));
}
if (_settings.Replace)
{
var backup = GetBackupPath();
File.Replace(path, _file, backup, ignoreMetadataErrors: true);
_fileSystem.File.Replace(path, _file, backup, ignoreMetadataErrors: true);
FileSystem.DeleteFile(backup, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
}
}
@@ -179,16 +183,17 @@ namespace ImageResizer.Models
private string GetDestinationPath(BitmapEncoder encoder)
{
var directory = _destinationDirectory ?? Path.GetDirectoryName(_file);
var originalFileName = Path.GetFileNameWithoutExtension(_file);
var directory = _destinationDirectory ?? _fileSystem.Path.GetDirectoryName(_file);
var originalFileName = _fileSystem.Path.GetFileNameWithoutExtension(_file);
var supportedExtensions = encoder.CodecInfo.FileExtensions.Split(',');
var extension = Path.GetExtension(_file);
var extension = _fileSystem.Path.GetExtension(_file);
if (!supportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
extension = supportedExtensions.FirstOrDefault();
}
// Using CurrentCulture since this is user facing
var fileName = string.Format(
CultureInfo.CurrentCulture,
_settings.FileNameFormat,
@@ -198,11 +203,11 @@ namespace ImageResizer.Models
_settings.SelectedSize.Height,
encoder.Frames[0].PixelWidth,
encoder.Frames[0].PixelHeight);
var path = Path.Combine(directory, fileName + extension);
var path = _fileSystem.Path.Combine(directory, fileName + extension);
var uniquifier = 1;
while (File.Exists(path))
while (_fileSystem.File.Exists(path))
{
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + extension);
path = _fileSystem.Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + extension);
}
return path;
@@ -210,15 +215,15 @@ namespace ImageResizer.Models
private string GetBackupPath()
{
var directory = Path.GetDirectoryName(_file);
var fileName = Path.GetFileNameWithoutExtension(_file);
var extension = Path.GetExtension(_file);
var directory = _fileSystem.Path.GetDirectoryName(_file);
var fileName = _fileSystem.Path.GetFileNameWithoutExtension(_file);
var extension = _fileSystem.Path.GetExtension(_file);
var path = Path.Combine(directory, fileName + ".bak" + extension);
var path = _fileSystem.Path.Combine(directory, fileName + ".bak" + extension);
var uniquifier = 1;
while (File.Exists(path))
while (_fileSystem.File.Exists(path))
{
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + ".bak" + extension);
path = _fileSystem.Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + ".bak" + extension);
}
return path;

View File

@@ -9,7 +9,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Threading;
using System.Windows.Media.Imaging;
using ImageResizer.Models;
@@ -22,9 +22,11 @@ namespace ImageResizer.Properties
[JsonObject(MemberSerialization.OptIn)]
public sealed partial class Settings : IDataErrorInfo, INotifyPropertyChanged
{
private static readonly IFileSystem _fileSystem = new FileSystem();
// Used to synchronize access to the settings.json file
private static Mutex _jsonMutex = new Mutex();
private static string _settingsPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "ImageResizer", "settings.json");
private static string _settingsPath = _fileSystem.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "Microsoft", "PowerToys", "ImageResizer", "settings.json");
private string _fileNameFormat;
private bool _shrinkOnly;
private int _selectedSizeIndex;
@@ -63,6 +65,7 @@ namespace ImageResizer.Properties
public IEnumerable<ResizeSize> AllSizes { get; set; }
// Using OrdinalIgnoreCase since this is internal and used for comparison with symbols
public string FileNameFormat
=> _fileNameFormat
?? (_fileNameFormat = FileName
@@ -111,6 +114,7 @@ namespace ImageResizer.Properties
if (JpegQualityLevel < 1 || JpegQualityLevel > 100)
{
// Using CurrentCulture since this is user facing
return string.Format(CultureInfo.CurrentCulture, Resources.ValueMustBeBetween, 1, 100);
}
@@ -382,25 +386,25 @@ namespace ImageResizer.Properties
jsonData += "}";
// Create directory if it doesn't exist
FileInfo file = new FileInfo(SettingsPath);
IFileInfo file = _fileSystem.FileInfo.FromFileName(SettingsPath);
file.Directory.Create();
// write string to file
File.WriteAllText(SettingsPath, jsonData);
_fileSystem.File.WriteAllText(SettingsPath, jsonData);
_jsonMutex.ReleaseMutex();
}
public void Reload()
{
_jsonMutex.WaitOne();
if (!File.Exists(SettingsPath))
if (!_fileSystem.File.Exists(SettingsPath))
{
_jsonMutex.ReleaseMutex();
Save();
return;
}
string jsonData = File.ReadAllText(SettingsPath);
string jsonData = _fileSystem.File.ReadAllText(SettingsPath);
JObject imageResizerSettings = JObject.Parse(jsonData);
// Replace the { "value": <Value> } with <Value> to match the Settings object format

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Documents;
namespace ImageResizer.Views
{
public class AccessibleHyperlink : Hyperlink
{
public AutomationControlType ControlType { get; set; }
protected override AutomationPeer OnCreateAutomationPeer()
{
var peer = new CustomizableHyperlinkAutomationPeer(this);
peer.ControlType = ControlType;
return peer;
}
}
}

View File

@@ -114,18 +114,18 @@
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Column="6" Margin="5,0,0,0" VerticalAlignment="Center">
<Hyperlink Command="{Binding DataContext.RemoveSizeCommand,ElementName=_this}" CommandParameter="{Binding}">
<local:AccessibleHyperlink ControlType="Button" Command="{Binding DataContext.RemoveSizeCommand,ElementName=_this}" CommandParameter="{Binding}">
<Run Text="{x:Static p:Resources.Advanced_DeleteSize}"/>
</Hyperlink>
</local:AccessibleHyperlink>
</TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock>
<Hyperlink Command="{Binding AddSizeCommand}">
<local:AccessibleHyperlink ControlType="Button" Command="{Binding AddSizeCommand}">
<Run Text="{x:Static p:Resources.Advanced_CreateSize}"/>
</Hyperlink>
</local:AccessibleHyperlink>
</TextBlock>
</StackPanel>
</TabItem>

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Windows.Automation.Peers;
using System.Windows.Documents;
namespace ImageResizer.Views
{
public class CustomizableHyperlinkAutomationPeer : HyperlinkAutomationPeer
{
public CustomizableHyperlinkAutomationPeer(Hyperlink owner)
: base(owner)
{
}
public AutomationControlType ControlType { get; set; }
protected override AutomationControlType GetAutomationControlTypeCore()
{
return ControlType;
}
}
}

View File

@@ -133,9 +133,9 @@
<TextBlock VerticalAlignment="Center"
Visibility="{Binding ShowAdvancedSettings, Converter={StaticResource BoolValueConverter}}">
<Hyperlink Command="{Binding ShowAdvancedCommand}">
<local:AccessibleHyperlink ControlType="Button" Command="{Binding ShowAdvancedCommand}">
<Run Text="{x:Static p:Resources.Input_ShowAdvanced}"/>
</Hyperlink>
</local:AccessibleHyperlink>
</TextBlock>
<Button Grid.Column="1"