Skip to content

Commit 25b1e52

Browse files
committed
Sync with latest in main
2 parents 1033647 + 3e0f70f commit 25b1e52

File tree

86 files changed

+1313
-1787
lines changed

Some content is hidden

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

86 files changed

+1313
-1787
lines changed

src/Files.Backend/Services/Settings/IAppearanceSettingsService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,10 @@ public interface IAppearanceSettingsService : IBaseSettingsService, INotifyPrope
6262
/// Gets or sets a value indicating whether or not recycle bin should be pinned to the sidebar.
6363
/// </summary>
6464
bool PinRecycleBinToSidebar { get; set; }
65+
66+
/// <summary>
67+
/// Gets or sets a value indicating whether or not to use the compact styles.
68+
/// </summary>
69+
bool UseCompactStyles { get; set; }
6570
}
6671
}

src/Files.Launcher/Helpers/ShellNewMenuHelper.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ private static async Task<ShellNewEntry> GetShellNewRegistryEntries(RegistryKey
6969
private static async Task<ShellNewEntry> ParseShellNewRegistryEntry(RegistryKey key, RegistryKey root)
7070
{
7171
var valueNames = key.GetValueNames();
72-
if (!valueNames.Contains("NullFile") &&
73-
!valueNames.Contains("ItemName") &&
74-
!valueNames.Contains("FileName"))
72+
if (!valueNames.Contains("NullFile", StringComparer.OrdinalIgnoreCase) &&
73+
!valueNames.Contains("ItemName", StringComparer.OrdinalIgnoreCase) &&
74+
!valueNames.Contains("FileName", StringComparer.OrdinalIgnoreCase) &&
75+
!valueNames.Contains("Command", StringComparer.OrdinalIgnoreCase))
7576
{
7677
return null;
7778
}

src/Files.Launcher/MessageHandlers/Win32MessageHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public async Task ParseArgumentsAsync(PipeStream connection, Dictionary<string,
163163
var dataPath = Environment.ExpandEnvironmentVariables("%LocalAppData%\\Files");
164164
if (enable)
165165
{
166-
if (!Win32API.RunPowershellCommand($"-command \"New-Item -Force -Path {dataPath} -ItemType Directory; Copy-Item -Filter *.* -Path '{destFolder}\\*' -Recurse -Force -Destination '{dataPath}'\"", false))
166+
if (!Win32API.RunPowershellCommand($"-command \"New-Item -Force -Path '{dataPath}' -ItemType Directory; Copy-Item -Filter *.* -Path '{destFolder}\\*' -Recurse -Force -Destination '{dataPath}'\"", false))
167167
{
168168
// Error copying files
169169
DetectIsSetAsDefaultFileManager();

src/Files.OpenDialog/CustomOpenDialog/CustomOpenDialog.vcxproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
170170
</Link>
171171
<PostBuildEvent>
172-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
172+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
173173
</PostBuildEvent>
174174
</ItemDefinitionGroup>
175175
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -205,7 +205,7 @@
205205
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
206206
</Link>
207207
<PostBuildEvent>
208-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
208+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
209209
</PostBuildEvent>
210210
</ItemDefinitionGroup>
211211
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm64'">
@@ -242,7 +242,7 @@
242242
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
243243
</Link>
244244
<PostBuildEvent>
245-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
245+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
246246
</PostBuildEvent>
247247
</ItemDefinitionGroup>
248248
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -281,7 +281,7 @@
281281
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
282282
</Link>
283283
<PostBuildEvent>
284-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
284+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
285285
</PostBuildEvent>
286286
</ItemDefinitionGroup>
287287
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -319,7 +319,7 @@
319319
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
320320
</Link>
321321
<PostBuildEvent>
322-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
322+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
323323
</PostBuildEvent>
324324
</ItemDefinitionGroup>
325325
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm64'">
@@ -358,7 +358,7 @@
358358
<OutputFile>$(OutDir)CustomOpenDialog$(PlatformArchitecture)$(TargetExt)</OutputFile>
359359
</Link>
360360
<PostBuildEvent>
361-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.dll $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
361+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.dll" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
362362
</PostBuildEvent>
363363
</ItemDefinitionGroup>
364364
<ItemGroup>

src/Files.OpenDialog/FilesLauncher/FilesLauncher.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,6 @@ bool OpenInExistingShellWindow(const TCHAR* folderPath)
340340

341341
bool opened = false;
342342
IShellWindows* shellWindows;
343-
long shellWindowsCount;
344343
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_IShellWindows, (void**)&shellWindows)))
345344
{
346345
VARIANT v;

src/Files.OpenDialog/FilesLauncher/FilesLauncher.vcxproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
136136
</Link>
137137
<PostBuildEvent>
138-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
138+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
139139
</PostBuildEvent>
140140
</ItemDefinitionGroup>
141141
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -156,7 +156,7 @@
156156
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
157157
</Link>
158158
<PostBuildEvent>
159-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
159+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
160160
</PostBuildEvent>
161161
</ItemDefinitionGroup>
162162
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -173,7 +173,7 @@
173173
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
174174
</Link>
175175
<PostBuildEvent>
176-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
176+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
177177
</PostBuildEvent>
178178
</ItemDefinitionGroup>
179179
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm64'">
@@ -190,7 +190,7 @@
190190
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
191191
</Link>
192192
<PostBuildEvent>
193-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
193+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
194194
</PostBuildEvent>
195195
</ItemDefinitionGroup>
196196
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -211,7 +211,7 @@
211211
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
212212
</Link>
213213
<PostBuildEvent>
214-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
214+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
215215
</PostBuildEvent>
216216
</ItemDefinitionGroup>
217217
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm64'">
@@ -232,7 +232,7 @@
232232
<OutputFile>$(OutDir)FilesLauncher$(TargetExt)</OutputFile>
233233
</Link>
234234
<PostBuildEvent>
235-
<Command>xcopy /s /y $(ProjectDir)$(OutDir)*.exe $(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog</Command>
235+
<Command>xcopy /s /y "$(ProjectDir)$(OutDir)*.exe" "$(ProjectDir)..\..\..\src\Files.Launcher\Assets\FilesOpenDialog"</Command>
236236
</PostBuildEvent>
237237
</ItemDefinitionGroup>
238238
<ItemGroup>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using System.Runtime.InteropServices.ComTypes;
3+
4+
namespace Files.Shared.Extensions
5+
{
6+
public static class DateExtensions
7+
{
8+
public static DateTime ToDateTime(this FILETIME time)
9+
{
10+
uint low = (uint)time.dwLowDateTime;
11+
ulong high = (ulong)time.dwHighDateTime;
12+
long fileTime = (long)((high << 32) + low);
13+
try
14+
{
15+
return DateTime.FromFileTimeUtc(fileTime);
16+
}
17+
catch
18+
{
19+
return DateTime.FromFileTimeUtc(0xFFFFFFFF);
20+
}
21+
}
22+
}
23+
}

src/Files.Shared/Extensions/LinqExtensions.cs

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,52 @@
33
using System.Linq;
44
using System.Threading.Tasks;
55

6-
#nullable enable
7-
86
namespace Files.Shared.Extensions
97
{
108
public static class LinqExtensions
119
{
12-
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
13-
this IEnumerable<TSource> source,
14-
IEnumerable<TSource> other,
15-
Func<TSource, TKey> keySelector)
10+
/// <summary>
11+
/// Determines whether <paramref name="enumerable"/> is empty or not.
12+
/// <br/><br/>
13+
/// Remarks:
14+
/// <br/>
15+
/// This function is faster than enumerable.Count == 0 since it'll only iterate one element instead of all elements.
16+
/// <br/>
17+
/// This function is null-safe.
18+
/// </summary>
19+
/// <typeparam name="T"></typeparam>
20+
/// <param name="enumerable"></param>
21+
/// <returns></returns>
22+
public static bool IsEmpty<T>(this IEnumerable<T> enumerable) => enumerable is null || !enumerable.Any();
23+
24+
public static TOut? Get<TOut, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TOut? defaultValue = default)
25+
{
26+
if (dictionary is null || key is null)
27+
{
28+
return default;
29+
}
30+
if (!dictionary.ContainsKey(key))
31+
{
32+
if (defaultValue is TValue value)
33+
dictionary.Add(key, value);
34+
else
35+
dictionary.Remove(key);
36+
return defaultValue;
37+
}
38+
if (dictionary[key] is TOut o)
39+
{
40+
return o;
41+
}
42+
return default;
43+
}
44+
45+
public static async Task<IEnumerable<T>> WhereAsync<T>(this IEnumerable<T> source, Func<T, Task<bool>> predicate)
46+
{
47+
var results = await Task.WhenAll(source.Select(async x => (x, await predicate(x))));
48+
return results.Where(x => x.Item2).Select(x => x.x);
49+
}
50+
51+
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> source, IEnumerable<TSource> other, Func<TSource, TKey> keySelector)
1652
{
1753
var set = new HashSet<TKey>(other.Select(keySelector));
1854
foreach (var item in source)
@@ -25,74 +61,61 @@ public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
2561
}
2662

2763
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> property)
28-
{
29-
return items.GroupBy(property).Select(x => x.First());
30-
}
64+
=> items.GroupBy(property).Select(x => x.First());
3165

32-
public static async Task<IEnumerable<T>> WhereAsync<T>(this IEnumerable<T> source, Func<T, Task<bool>> predicate)
33-
{
34-
var results = await Task.WhenAll(source.Select(async x => (x, await predicate(x))));
35-
return results.Where(x => x.Item2).Select(x => x.Item1);
36-
}
66+
public static IEnumerable<T> IntersectBy<T, TKey>(this IEnumerable<T> items, IEnumerable<T> others, Func<T, TKey> keySelector)
67+
=> items.Join(others.Select(keySelector), keySelector, id => id, (o, id) => o);
3768

38-
public static IEnumerable<TSource> IntersectBy<TSource, TKey>(
39-
this IEnumerable<TSource> source,
40-
IEnumerable<TSource> other,
41-
Func<TSource, TKey> keySelector)
69+
/// <summary>
70+
/// Enumerates through <see cref="IEnumerable{T}"/> of elements and executes <paramref name="action"/>
71+
/// </summary>
72+
/// <typeparam name="T">Element of <paramref name="collection"/></typeparam>
73+
/// <param name="collection">The collection to enumerate through</param>
74+
/// <param name="action">The action to take every element</param>
75+
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
4276
{
43-
return source.Join(other.Select(keySelector), keySelector, id => id, (o, id) => o);
77+
foreach (T value in collection)
78+
action(value);
4479
}
4580

46-
public static TOut? Get<TOut, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TOut? defaultValue = default)
81+
public static IList<T> AddSorted<T>(this IList<T> list, T item) where T : IComparable<T>
4782
{
48-
// If dictionary is null or key is invalid, return default.
49-
if (dictionary == null || key == null)
83+
if (!list.Any() || list.Last().CompareTo(item) <= 0)
5084
{
51-
return defaultValue;
85+
list.Add(item);
86+
return list;
5287
}
53-
54-
// If setting doesn't exist, create it.
55-
if (!dictionary.ContainsKey(key))
88+
if (list[0].CompareTo(item) >= 0)
5689
{
57-
dictionary[key] = (TValue)(object)defaultValue;
90+
list.Insert(0, item);
91+
return list;
5892
}
59-
60-
return (TOut)(object)dictionary[key];
61-
}
62-
63-
public static DateTime ToDateTime(this System.Runtime.InteropServices.ComTypes.FILETIME time)
64-
{
65-
ulong high = (ulong)time.dwHighDateTime;
66-
uint low = (uint)time.dwLowDateTime;
67-
long fileTime = (long)((high << 32) + low);
68-
try
69-
{
70-
return DateTime.FromFileTimeUtc(fileTime);
71-
}
72-
catch
93+
int index = list.ToList().BinarySearch(item);
94+
if (index < 0)
7395
{
74-
return DateTime.FromFileTimeUtc(0xFFFFFFFF);
96+
index = ~index;
7597
}
98+
list.Insert(index, item);
99+
return list;
76100
}
77101

78-
public static async Task WithTimeoutAsync(this Task task,
79-
TimeSpan timeout)
102+
/// <summary>
103+
/// Removes all elements from the specified index to the end of the list.
104+
/// </summary>
105+
/// <typeparam name="T"></typeparam>
106+
/// <param name="list"></param>
107+
/// <param name="index"></param>
108+
public static List<T> RemoveFrom<T>(this List<T> list, int index)
80109
{
81-
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
110+
if (!list.Any())
82111
{
83-
await task;
112+
return list;
84113
}
85-
}
86-
87-
public static async Task<T?> WithTimeoutAsync<T>(this Task<T> task,
88-
TimeSpan timeout, T? defaultValue = default)
89-
{
90-
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
114+
if (index <= 0)
91115
{
92-
return await task;
116+
return new List<T>(0);
93117
}
94-
95-
return defaultValue;
118+
return list.Take(index - 1).ToList();
96119
}
97120
}
98121
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
namespace Files.Shared.Extensions
5+
{
6+
public static class TaskExtensions
7+
{
8+
public static async Task WithTimeoutAsync(this Task task, TimeSpan timeout)
9+
{
10+
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
11+
{
12+
await task;
13+
}
14+
}
15+
16+
public static async Task<T?> WithTimeoutAsync<T>(this Task<T> task, TimeSpan timeout, T? defaultValue = default)
17+
{
18+
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
19+
{
20+
return await task;
21+
}
22+
return defaultValue;
23+
}
24+
}
25+
}

src/Files.Uwp/App.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
<FontFamily x:Key="RecycleBinIcons">/Assets/Custom Glyphs/recyclebin-fabric-glyph.ttf#Fabric MDL2 Assets</FontFamily>
2626
<FontFamily x:Key="ColoredIconFontFamily">/Assets/Custom Glyphs/Colored-Icons.ttf#Untitled1</FontFamily>
2727

28+
<!-- Default list view item height -->
29+
<x:Double x:Key="ListItemHeight">36</x:Double>
2830
<ResourceDictionary.MergedDictionaries>
2931
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" ControlsResourcesVersion="Version2" />
3032
<ResourceDictionary>

0 commit comments

Comments
 (0)