Skip to content

Commit fb2b958

Browse files
authored
Show localized names for system folders (#3561)
1 parent 663099c commit fb2b958

File tree

7 files changed

+177
-34
lines changed

7 files changed

+177
-34
lines changed

Files/Helpers/BulkConcurrentObservableCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,4 @@ int IList.Add(object value)
257257
void IList.Remove(object value) => Remove((T)value);
258258
void ICollection.CopyTo(Array array, int index) => CopyTo((T[])array, index);
259259
}
260-
}
260+
}

Files/Helpers/FileListCache/FileListCacheController.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ private FileListCacheController()
2525
SizeLimit = 1_000_000
2626
});
2727

28+
private readonly IMemoryCache fileNamesCache = new MemoryCache(new MemoryCacheOptions
29+
{
30+
SizeLimit = 1_000_000
31+
});
32+
2833
public Task SaveFileListToCache(string path, CacheEntry cacheEntry)
2934
{
3035
if (!App.AppSettings.UseFileListCache)
@@ -67,5 +72,38 @@ public async Task<CacheEntry> ReadFileListFromCache(string path, CancellationTok
6772
}
6873
return entry;
6974
}
75+
76+
public async Task<string> ReadFileDisplayNameFromCache(string path, CancellationToken cancellationToken)
77+
{
78+
var displayName = fileNamesCache.Get<string>(path);
79+
if (displayName == null)
80+
{
81+
displayName = await persistentAdapter.ReadFileDisplayNameFromCache(path, cancellationToken);
82+
if (displayName != null)
83+
{
84+
fileNamesCache.Set(path, displayName, new MemoryCacheEntryOptions
85+
{
86+
Size = 1
87+
});
88+
}
89+
}
90+
return displayName;
91+
}
92+
93+
public Task SaveFileDisplayNameToCache(string path, string displayName)
94+
{
95+
if (displayName == null)
96+
{
97+
filesCache.Remove(path);
98+
return persistentAdapter.SaveFileDisplayNameToCache(path, displayName);
99+
}
100+
filesCache.Set(path, displayName, new MemoryCacheEntryOptions
101+
{
102+
Size = 1
103+
});
104+
105+
// save entry to persistent cache in background
106+
return persistentAdapter.SaveFileDisplayNameToCache(path, displayName);
107+
}
70108
}
71109
}

Files/Helpers/FileListCache/IFileListCache.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@ internal interface IFileListCache
88
public Task<CacheEntry> ReadFileListFromCache(string path, CancellationToken cancellationToken);
99

1010
public Task SaveFileListToCache(string path, CacheEntry cacheEntry);
11+
12+
public Task<string> ReadFileDisplayNameFromCache(string path, CancellationToken cancellationToken);
13+
14+
public Task SaveFileDisplayNameToCache(string path, string displayName);
1115
}
1216
}

Files/Helpers/FileListCache/PersistentSQLiteCacheAdapter.cs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,37 @@ public PersistentSQLiteCacheAdapter()
2020
var localCacheFolder = ApplicationData.Current.LocalCacheFolder.Path;
2121
string dbPath = Path.Combine(localCacheFolder, "cache.db");
2222

23-
bool schemaCreated = File.Exists(dbPath);
24-
25-
SQLitePCL.Batteries_V2.Init();
23+
try
24+
{
25+
SQLitePCL.Batteries_V2.Init();
2626

27-
connection = new SqliteConnection($"Data Source='{dbPath}'");
28-
connection.Open();
27+
connection = new SqliteConnection($"Data Source='{dbPath}'");
28+
connection.Open();
2929

30-
if (!schemaCreated)
31-
{
3230
// create db schema
33-
var createSql = @"CREATE TABLE IF NOT EXISTS ""FileListCache"" (
31+
var createFileListCacheTable = @"CREATE TABLE IF NOT EXISTS ""FileListCache"" (
3432
""Id"" VARCHAR(5000) NOT NULL,
3533
""Timestamp"" INTEGER NOT NULL,
3634
""Entry"" TEXT NOT NULL,
3735
PRIMARY KEY(""Id"")
3836
)";
39-
using var cmd = new SqliteCommand(createSql, connection);
40-
var result = cmd.ExecuteNonQuery();
41-
}
37+
using var cmdFileListCacheTable = new SqliteCommand(createFileListCacheTable, connection);
38+
cmdFileListCacheTable.ExecuteNonQuery();
39+
40+
var createFileDisplayNameCacheTable = @"CREATE TABLE IF NOT EXISTS ""FileDisplayNameCache"" (
41+
""Id"" VARCHAR(5000) NOT NULL,
42+
""DisplayName"" TEXT NOT NULL,
43+
PRIMARY KEY(""Id"")
44+
)";
45+
using var cmdFileDisplayNameCacheTable = new SqliteCommand(createFileDisplayNameCacheTable, connection);
46+
cmdFileDisplayNameCacheTable.ExecuteNonQuery();
4247

43-
RunCleanupRoutine();
48+
RunCleanupRoutine();
49+
}
50+
catch (Exception ex)
51+
{
52+
NLog.LogManager.GetCurrentClassLogger().Warn(ex, "Cache feature will not be available.");
53+
}
4454
}
4555

4656
public async Task SaveFileListToCache(string path, CacheEntry cacheEntry)
@@ -127,6 +137,65 @@ public async Task<CacheEntry> ReadFileListFromCache(string path, CancellationTok
127137
}
128138
}
129139

140+
public async Task SaveFileDisplayNameToCache(string path, string displayName)
141+
{
142+
try
143+
{
144+
if (displayName == null)
145+
{
146+
using var deleteCommand = new SqliteCommand("DELETE FROM FileDisplayNameCache WHERE Id = @Id", connection);
147+
deleteCommand.Parameters.Add("@Id", SqliteType.Text).Value = path;
148+
await deleteCommand.ExecuteNonQueryAsync();
149+
return;
150+
}
151+
152+
using var cmd = new SqliteCommand("SELECT Id FROM FileDisplayNameCache WHERE Id = @Id", connection);
153+
cmd.Parameters.Add("@Id", SqliteType.Text).Value = path;
154+
using var reader = await cmd.ExecuteReaderAsync();
155+
if (reader.HasRows)
156+
{
157+
// need to update entry
158+
using var updateCommand = new SqliteCommand("UPDATE FileDisplayNameCache SET DisplayName = @DisplayName WHERE Id = @Id", connection);
159+
updateCommand.Parameters.Add("@Id", SqliteType.Text).Value = path;
160+
updateCommand.Parameters.Add("@DisplayName", SqliteType.Text).Value = displayName;
161+
await updateCommand.ExecuteNonQueryAsync();
162+
}
163+
else
164+
{
165+
// need to insert entry
166+
using var insertCommand = new SqliteCommand("INSERT INTO FileDisplayNameCache (Id, DisplayName) VALUES (@Id, @DisplayName)", connection);
167+
insertCommand.Parameters.Add("@Id", SqliteType.Text).Value = path;
168+
insertCommand.Parameters.Add("@DisplayName", SqliteType.Text).Value = displayName;
169+
await insertCommand.ExecuteNonQueryAsync();
170+
}
171+
}
172+
catch (Exception ex)
173+
{
174+
Debug.WriteLine(ex.ToString());
175+
}
176+
}
177+
178+
public async Task<string> ReadFileDisplayNameFromCache(string path, CancellationToken cancellationToken)
179+
{
180+
try
181+
{
182+
using var cmd = new SqliteCommand("SELECT DisplayName FROM FileDisplayNameCache WHERE Id = @Id", connection);
183+
cmd.Parameters.Add("@Id", SqliteType.Text).Value = path;
184+
185+
using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
186+
if (!await reader.ReadAsync())
187+
{
188+
return null;
189+
}
190+
return reader.GetString(0);
191+
}
192+
catch (Exception ex)
193+
{
194+
Debug.WriteLine(ex.ToString());
195+
return null;
196+
}
197+
}
198+
130199
private long GetTimestamp(DateTime dateTime)
131200
{
132201
return new DateTimeOffset(dateTime).ToUnixTimeSeconds();

Files/ViewModels/ItemViewModel.cs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,10 @@ public string JumpString
325325
// use FilesAndFolders because only displayed entries should be jumped to
326326
var candidateItems = FilesAndFolders.Where(f => f.ItemName.Length >= value.Length && f.ItemName.Substring(0, value.Length).ToLower() == value);
327327

328-
if (AssociatedInstance.ContentPage != null && AssociatedInstance.ContentPage.IsItemSelected)
329-
{
330-
previouslySelectedItem = AssociatedInstance.ContentPage.SelectedItem;
331-
}
328+
if (AssociatedInstance.ContentPage != null && AssociatedInstance.ContentPage.IsItemSelected)
329+
{
330+
previouslySelectedItem = AssociatedInstance.ContentPage.SelectedItem;
331+
}
332332

333333
// If the user is trying to cycle through items
334334
// starting with the same letter
@@ -484,6 +484,19 @@ public void CancelExtendedPropertiesLoading()
484484
loadPropsCTS = new CancellationTokenSource();
485485
}
486486

487+
public async Task ApplySingleFileChangeAsync(ListedItem item)
488+
{
489+
var newIndex = filesAndFolders.IndexOf(item);
490+
await CoreApplication.MainView.ExecuteOnUIThreadAsync(() =>
491+
{
492+
FilesAndFolders.Remove(item);
493+
if (newIndex != -1)
494+
{
495+
FilesAndFolders.Insert(newIndex, item);
496+
}
497+
});
498+
}
499+
487500
// apply changes immediately after manipulating on filesAndFolders completed
488501
public async Task ApplyFilesAndFoldersChangesAsync()
489502
{
@@ -818,6 +831,20 @@ await CoreApplication.MainView.ExecuteOnUIThreadAsync(async () =>
818831
StorageFolder matchingStorageItem = await GetFolderFromPathAsync(item.ItemPath);
819832
if (matchingStorageItem != null)
820833
{
834+
if (matchingStorageItem.DisplayName != item.ItemName)
835+
{
836+
await CoreApplication.MainView.ExecuteOnUIThreadAsync(() =>
837+
{
838+
item.ItemName = matchingStorageItem.DisplayName;
839+
});
840+
await fileListCache.SaveFileDisplayNameToCache(item.ItemPath, matchingStorageItem.DisplayName);
841+
if (FolderSettings.DirectorySortOption == SortOption.Name && !isLoadingItems)
842+
{
843+
await OrderFilesAndFoldersAsync();
844+
await ApplySingleFileChangeAsync(item);
845+
//await SaveCurrentListToCacheAsync(WorkingDirectory);
846+
}
847+
}
821848
var syncStatus = await CheckCloudDriveSyncStatusAsync(matchingStorageItem);
822849
await CoreApplication.MainView.ExecuteOnUIThreadAsync(() =>
823850
{
@@ -1194,7 +1221,7 @@ await DialogDisplayHelper.ShowDialogAsync(
11941221
{
11951222
PrimaryItemAttribute = StorageItemTypes.Folder,
11961223
ItemPropertiesInitialized = true,
1197-
ItemName = rootFolder.Name,
1224+
ItemName = rootFolder.DisplayName,
11981225
ItemDateModifiedReal = basicProps.DateModified,
11991226
ItemType = rootFolder.DisplayType,
12001227
LoadFolderGlyph = true,
@@ -1312,7 +1339,7 @@ await Task.Run(async () =>
13121339
{
13131340
if (findData.cFileName != "." && findData.cFileName != "..")
13141341
{
1315-
var listedItem = AddFolder(findData, path, returnformat);
1342+
var listedItem = await AddFolder(findData, path, returnformat);
13161343
if (listedItem != null)
13171344
{
13181345
if (skipItems?.Contains(listedItem.ItemPath) ?? false)
@@ -1816,10 +1843,10 @@ private async Task AddFileOrFolderAsync(string fileOrFolderPath, string dateRetu
18161843

18171844
FindClose(hFile);
18181845

1819-
ListedItem listedItem = null;
1846+
ListedItem listedItem;
18201847
if ((findData.dwFileAttributes & 0x10) > 0) // FILE_ATTRIBUTE_DIRECTORY
18211848
{
1822-
listedItem = AddFolder(findData, Directory.GetParent(fileOrFolderPath).FullName, dateReturnFormat);
1849+
listedItem = await AddFolder(findData, Directory.GetParent(fileOrFolderPath).FullName, dateReturnFormat);
18231850
}
18241851
else
18251852
{
@@ -1939,7 +1966,7 @@ public async Task RemoveFileOrFolderAsync(string path)
19391966
}
19401967
}
19411968

1942-
private ListedItem AddFolder(WIN32_FIND_DATA findData, string pathRoot, string dateReturnFormat)
1969+
private async Task<ListedItem> AddFolder(WIN32_FIND_DATA findData, string pathRoot, string dateReturnFormat)
19431970
{
19441971
if (addFilesCTS.IsCancellationRequested)
19451972
{
@@ -1967,8 +1994,13 @@ private ListedItem AddFolder(WIN32_FIND_DATA findData, string pathRoot, string d
19671994
// Invalid date means invalid findData, do not add to list
19681995
return null;
19691996
}
1970-
var itemPath = Path.Combine(pathRoot, findData.cFileName);
19711997

1998+
var itemPath = Path.Combine(pathRoot, findData.cFileName);
1999+
string itemName = await fileListCache.ReadFileDisplayNameFromCache(itemPath, addFilesCTS.Token);
2000+
if (string.IsNullOrEmpty(itemName))
2001+
{
2002+
itemName = findData.cFileName;
2003+
}
19722004
bool isHidden = (((FileAttributes)findData.dwFileAttributes & FileAttributes.Hidden) == FileAttributes.Hidden);
19732005
double opacity = 1;
19742006

@@ -1980,7 +2012,7 @@ private ListedItem AddFolder(WIN32_FIND_DATA findData, string pathRoot, string d
19802012
return new ListedItem(null, dateReturnFormat)
19812013
{
19822014
PrimaryItemAttribute = StorageItemTypes.Folder,
1983-
ItemName = findData.cFileName,
2015+
ItemName = itemName,
19842016
ItemDateModifiedReal = itemModifiedDate,
19852017
ItemDateCreatedReal = itemCreatedDate,
19862018
ItemType = "FileFolderListItem".GetLocalized(),
@@ -2179,7 +2211,7 @@ private async Task<ListedItem> AddFolderAsync(StorageFolder folder, string dateR
21792211
return new ListedItem(folder.FolderRelativeId, dateReturnFormat)
21802212
{
21812213
PrimaryItemAttribute = StorageItemTypes.Folder,
2182-
ItemName = folder.Name,
2214+
ItemName = folder.DisplayName,
21832215
ItemDateModifiedReal = basicProperties.DateModified,
21842216
ItemDateCreatedReal = dateCreated,
21852217
ItemType = folder.DisplayType,

Files/Views/LayoutModes/GridViewBrowser.xaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@
594594
Background="Transparent"
595595
IsRightTapEnabled="True"
596596
RightTapped="StackPanel_RightTapped"
597-
ToolTipService.ToolTip="{x:Bind ItemName}">
597+
ToolTipService.ToolTip="{x:Bind ItemName, Mode=OneWay}">
598598
<Grid.RowDefinitions>
599599
<RowDefinition Height="Auto" />
600600
<RowDefinition Height="Auto" />
@@ -706,7 +706,7 @@
706706
Grid.Column="1"
707707
HorizontalAlignment="Stretch"
708708
VerticalAlignment="Stretch"
709-
Text="{x:Bind ItemName}"
709+
Text="{x:Bind ItemName, Mode=OneWay}"
710710
TextTrimming="CharacterEllipsis"
711711
TextWrapping="NoWrap" />
712712
</Grid>
@@ -720,7 +720,7 @@
720720
Margin="0"
721721
HorizontalAlignment="Stretch"
722722
VerticalAlignment="Stretch"
723-
Text="{x:Bind ItemName}"
723+
Text="{x:Bind ItemName, Mode=OneWay}"
724724
TextAlignment="Center"
725725
TextChanged="GridViewTextBoxItemName_TextChanged"
726726
TextWrapping="Wrap" />
@@ -739,7 +739,7 @@
739739
Background="Transparent"
740740
IsRightTapEnabled="True"
741741
RightTapped="StackPanel_RightTapped"
742-
ToolTipService.ToolTip="{x:Bind ItemName}">
742+
ToolTipService.ToolTip="{x:Bind ItemName, Mode=OneWay}">
743743
<Grid.ColumnDefinitions>
744744
<ColumnDefinition Width="Auto" />
745745
<ColumnDefinition Width="90" />
@@ -845,7 +845,7 @@
845845
Margin="0,0,10,0"
846846
HorizontalAlignment="Left"
847847
ScrollViewer.VerticalScrollBarVisibility="Auto"
848-
Text="{x:Bind ItemName}"
848+
Text="{x:Bind ItemName, Mode=OneWay}"
849849
TextAlignment="Left"
850850
TextTrimming="CharacterEllipsis"
851851
TextWrapping="Wrap" />
@@ -856,7 +856,7 @@
856856
Margin="0,0,10,0"
857857
HorizontalAlignment="Left"
858858
ScrollViewer.VerticalScrollBarVisibility="Auto"
859-
Text="{x:Bind ItemName}"
859+
Text="{x:Bind ItemName, Mode=OneWay}"
860860
TextAlignment="Left"
861861
TextWrapping="Wrap"
862862
Visibility="Collapsed" />

Files/Views/ModernShellPage.xaml.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ private async void SetAddressBarSuggestions(AutoSuggestBox sender, int maxSugges
474474
suggestions = currPath.Select(x => new ListedItem(null)
475475
{
476476
ItemPath = x.Path,
477-
ItemName = x.Folder.Name
477+
ItemName = x.Folder.DisplayName
478478
}).ToList();
479479
}
480480
else if (currPath.Any())
@@ -483,12 +483,12 @@ private async void SetAddressBarSuggestions(AutoSuggestBox sender, int maxSugges
483483
suggestions = currPath.Select(x => new ListedItem(null)
484484
{
485485
ItemPath = x.Path,
486-
ItemName = x.Folder.Name
486+
ItemName = x.Folder.DisplayName
487487
}).Concat(
488488
subPath.Select(x => new ListedItem(null)
489489
{
490490
ItemPath = x.Path,
491-
ItemName = Path.Combine(currPath.First().Folder.Name, x.Folder.Name)
491+
ItemName = Path.Combine(currPath.First().Folder.DisplayName, x.Folder.DisplayName)
492492
})).ToList();
493493
}
494494
else

0 commit comments

Comments
 (0)