Skip to content

Commit 141aa4a

Browse files
authored
Feature: Added support for displaying background images in folders (#15632)
1 parent 25063a3 commit 141aa4a

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

src/Files.App/ViewModels/ShellViewModel.cs

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Files.Shared.Helpers;
66
using LibGit2Sharp;
77
using Microsoft.Extensions.Logging;
8+
using Microsoft.UI.Xaml;
89
using Microsoft.UI.Xaml.Data;
910
using Microsoft.UI.Xaml.Media;
1011
using Microsoft.UI.Xaml.Media.Imaging;
@@ -73,6 +74,41 @@ public string? SolutionFilePath
7374
private set => SetProperty(ref _SolutionFilePath, value);
7475
}
7576

77+
private ImageSource? _FolderBackgroundImageSource;
78+
public ImageSource? FolderBackgroundImageSource
79+
{
80+
get => _FolderBackgroundImageSource;
81+
private set => SetProperty(ref _FolderBackgroundImageSource, value);
82+
}
83+
84+
private float _FolderBackgroundImageOpacity = 1f;
85+
public float FolderBackgroundImageOpacity
86+
{
87+
get => _FolderBackgroundImageOpacity;
88+
private set => SetProperty(ref _FolderBackgroundImageOpacity, value);
89+
}
90+
91+
private Stretch _FolderBackgroundImageFit = Stretch.UniformToFill;
92+
public Stretch FolderBackgroundImageFit
93+
{
94+
get => _FolderBackgroundImageFit;
95+
private set => SetProperty(ref _FolderBackgroundImageFit, value);
96+
}
97+
98+
private VerticalAlignment _FolderBackgroundImageVerticalAlignment = VerticalAlignment.Center;
99+
public VerticalAlignment FolderBackgroundImageVerticalAlignment
100+
{
101+
get => _FolderBackgroundImageVerticalAlignment;
102+
private set => SetProperty(ref _FolderBackgroundImageVerticalAlignment, value);
103+
}
104+
105+
private HorizontalAlignment _FolderBackgroundImageHorizontalAlignment = HorizontalAlignment.Center;
106+
public HorizontalAlignment FolderBackgroundImageHorizontalAlignment
107+
{
108+
get => _FolderBackgroundImageHorizontalAlignment;
109+
private set => SetProperty(ref _FolderBackgroundImageHorizontalAlignment, value);
110+
}
111+
76112
private GitProperties _EnabledGitProperties;
77113
public GitProperties EnabledGitProperties
78114
{
@@ -495,11 +531,17 @@ public ShellViewModel(LayoutPreferencesManager folderSettingsViewModel)
495531
fileTagsSettingsService.OnSettingImportedEvent += FileTagsSettingsService_OnSettingUpdated;
496532
fileTagsSettingsService.OnTagsUpdated += FileTagsSettingsService_OnSettingUpdated;
497533
folderSizeProvider.SizeChanged += FolderSizeProvider_SizeChanged;
534+
folderSettings.LayoutModeChangeRequested += LayoutModeChangeRequested;
498535
RecycleBinManager.Default.RecycleBinItemCreated += RecycleBinItemCreatedAsync;
499536
RecycleBinManager.Default.RecycleBinItemDeleted += RecycleBinItemDeletedAsync;
500537
RecycleBinManager.Default.RecycleBinRefreshRequested += RecycleBinRefreshRequestedAsync;
501538
}
502539

540+
private async void LayoutModeChangeRequested(object? sender, LayoutModeEventArgs e)
541+
{
542+
await dispatcherQueue.EnqueueOrInvokeAsync(CheckForBackgroundImage, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
543+
}
544+
503545
private async void RecycleBinRefreshRequestedAsync(object sender, FileSystemEventArgs e)
504546
{
505547
if (!Constants.UserEnvironmentPaths.RecycleBinPath.Equals(CurrentFolder?.ItemPath, StringComparison.OrdinalIgnoreCase))
@@ -542,7 +584,7 @@ private async void RecycleBinItemCreatedAsync(object sender, FileSystemEventArgs
542584
await ApplyFilesAndFoldersChangesAsync();
543585
}
544586

545-
private async void FolderSizeProvider_SizeChanged(object? sender, SizeChangedEventArgs e)
587+
private async void FolderSizeProvider_SizeChanged(object? sender, Services.SizeProvider.SizeChangedEventArgs e)
546588
{
547589
try
548590
{
@@ -1003,7 +1045,8 @@ await dispatcherQueue.EnqueueOrInvokeAsync(async () =>
10031045
if (loadNonCachedThumbnail)
10041046
{
10051047
// Get non-cached thumbnail asynchronously
1006-
_ = Task.Run(async () => {
1048+
_ = Task.Run(async () =>
1049+
{
10071050
await loadThumbnailSemaphore.WaitAsync(cancellationToken);
10081051
try
10091052
{
@@ -1186,7 +1229,8 @@ await dispatcherQueue.EnqueueOrInvokeAsync(() =>
11861229
// Try loading thumbnail for cloud files in case they weren't cached the first time
11871230
if (item.SyncStatusUI.SyncStatus != CloudDriveSyncStatus.NotSynced && item.SyncStatusUI.SyncStatus != CloudDriveSyncStatus.Unknown)
11881231
{
1189-
_ = Task.Run(async () => {
1232+
_ = Task.Run(async () =>
1233+
{
11901234
await Task.Delay(500);
11911235
cts.Token.ThrowIfCancellationRequested();
11921236
await LoadThumbnailAsync(item, cts.Token);
@@ -1691,6 +1735,7 @@ await Task.Run(async () =>
16911735
await OrderFilesAndFoldersAsync();
16921736
await ApplyFilesAndFoldersChangesAsync();
16931737
await dispatcherQueue.EnqueueOrInvokeAsync(CheckForSolutionFile, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
1738+
await dispatcherQueue.EnqueueOrInvokeAsync(CheckForBackgroundImage, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
16941739
});
16951740

16961741
rootFolder ??= await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path));
@@ -1751,6 +1796,56 @@ private void CheckForSolutionFile()
17511796
.FirstOrDefault()?.ItemPath;
17521797
}
17531798

1799+
public void CheckForBackgroundImage()
1800+
{
1801+
var iniPath = Path.Combine(WorkingDirectory, "desktop.ini");
1802+
if (!File.Exists(iniPath))
1803+
return;
1804+
1805+
// Read data
1806+
var lines = File.ReadLines(iniPath);
1807+
var keys = lines.Select(line => line.Split('='))
1808+
.Where(parts => parts.Length == 2)
1809+
.ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim());
1810+
1811+
// Image source
1812+
if (folderSettings.LayoutMode is not FolderLayoutModes.ColumnView && keys.TryGetValue("Files_BackgroundImage", out var backgroundImage))
1813+
FolderBackgroundImageSource = new BitmapImage
1814+
{
1815+
UriSource = new Uri(backgroundImage, UriKind.RelativeOrAbsolute),
1816+
CreateOptions = BitmapCreateOptions.IgnoreImageCache
1817+
};
1818+
else
1819+
{
1820+
FolderBackgroundImageSource = null;
1821+
return;
1822+
}
1823+
1824+
// Opacity
1825+
if (keys.TryGetValue("Files_BackgroundOpacity", out var backgroundOpacity) && float.TryParse(backgroundOpacity, out var opacity))
1826+
FolderBackgroundImageOpacity = opacity;
1827+
else
1828+
FolderBackgroundImageOpacity = 1f;
1829+
1830+
// Stretch
1831+
if (keys.TryGetValue("Files_BackgroundFit", out var backgroundFit) && Enum.TryParse<Stretch>(backgroundFit, out var fit))
1832+
FolderBackgroundImageFit = fit;
1833+
else
1834+
FolderBackgroundImageFit = Stretch.UniformToFill;
1835+
1836+
// VerticalAlignment
1837+
if (keys.TryGetValue("Files_BackgroundVerticalAlignment", out var verticalAlignment) && Enum.TryParse<VerticalAlignment>(verticalAlignment, out var vAlignment))
1838+
FolderBackgroundImageVerticalAlignment = vAlignment;
1839+
else
1840+
FolderBackgroundImageVerticalAlignment = VerticalAlignment.Center;
1841+
1842+
// HorizontalAlignment
1843+
if (keys.TryGetValue("Files_BackgroundHorizontalAlignment", out var horizontalAlignment) && Enum.TryParse<HorizontalAlignment>(horizontalAlignment, out var hAlignment))
1844+
FolderBackgroundImageHorizontalAlignment = hAlignment;
1845+
else
1846+
FolderBackgroundImageHorizontalAlignment = HorizontalAlignment.Center;
1847+
}
1848+
17541849
public async Task<CloudDriveSyncStatus> CheckCloudDriveSyncStatusAsync(IStorageItem item)
17551850
{
17561851
int? syncStatus = null;
@@ -2471,6 +2566,7 @@ public void Dispose()
24712566
fileTagsSettingsService.OnSettingImportedEvent -= FileTagsSettingsService_OnSettingUpdated;
24722567
fileTagsSettingsService.OnTagsUpdated -= FileTagsSettingsService_OnSettingUpdated;
24732568
folderSizeProvider.SizeChanged -= FolderSizeProvider_SizeChanged;
2569+
folderSettings.LayoutModeChangeRequested -= LayoutModeChangeRequested;
24742570
}
24752571
}
24762572

src/Files.App/Views/Shells/ModernShellPage.xaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@
5050
<ThemeShadow x:Name="ShellContentThemeShadow" x:FieldModifier="public" />
5151
</Grid.Shadow>
5252

53+
<Image
54+
HorizontalAlignment="{x:Bind ShellViewModel.FolderBackgroundImageHorizontalAlignment, Mode=OneWay}"
55+
VerticalAlignment="{x:Bind ShellViewModel.FolderBackgroundImageVerticalAlignment, Mode=OneWay}"
56+
Opacity="{x:Bind ShellViewModel.FolderBackgroundImageOpacity, Mode=OneWay}"
57+
Source="{x:Bind ShellViewModel.FolderBackgroundImageSource, Mode=OneWay}"
58+
Stretch="{x:Bind ShellViewModel.FolderBackgroundImageFit, Mode=OneWay}" />
59+
5360
<!-- Swipe Backward Icon -->
5461
<Border
5562
x:Name="BackIcon"

0 commit comments

Comments
 (0)