Populates with game-grouped backup cards. The StackPanel to populate (cleared first). All backups to display. Returns store info for an appId, or null if unknown. Resolves a WPF resource key (e.g. brush names). <param name="onP
(
Panel panel,
IReadOnlyList<BackupInfo> backups,
Func<uint, StoreAppInfo?> lookupStore,
Func<object, object> findResource,
Func<BackupInfo, StackPanel, Wpf.Ui.
| 28 | /// sorted to the top, given a blue tint, and labeled with a "recent" badge. |
| 29 | /// </param> |
| 30 | internal static void Build( |
| 31 | Panel panel, |
| 32 | IReadOnlyList<BackupInfo> backups, |
| 33 | Func<uint, StoreAppInfo?> lookupStore, |
| 34 | Func<object, object> findResource, |
| 35 | Func<BackupInfo, StackPanel, Wpf.Ui.Controls.Button, Task> onPreview, |
| 36 | Func<BackupInfo, Wpf.Ui.Controls.Button, Task> onRestore, |
| 37 | DateTime? highlightAfterUtc = null) |
| 38 | { |
| 39 | panel.Children.Clear(); |
| 40 | |
| 41 | // Group backups by app ID. A backup spanning multiple apps appears under each. |
| 42 | var byApp = new Dictionary<uint, List<BackupInfo>>(); |
| 43 | foreach (var backup in backups) |
| 44 | { |
| 45 | if (backup.AppIds.Count == 0) |
| 46 | { |
| 47 | if (!byApp.ContainsKey(0)) byApp[0] = new List<BackupInfo>(); |
| 48 | byApp[0].Add(backup); |
| 49 | } |
| 50 | else |
| 51 | { |
| 52 | foreach (uint appId in backup.AppIds) |
| 53 | { |
| 54 | if (!byApp.ContainsKey(appId)) byApp[appId] = new List<BackupInfo>(); |
| 55 | byApp[appId].Add(backup); |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | // Sort game groups: groups with recent backups first, then alphabetical by name, then by app ID |
| 61 | var sortedGroups = byApp.OrderBy(g => |
| 62 | { |
| 63 | bool hasRecent = highlightAfterUtc.HasValue && |
| 64 | g.Value.Any(b => b.Timestamp >= highlightAfterUtc.Value); |
| 65 | int recentOrder = hasRecent ? 0 : 1; |
| 66 | |
| 67 | if (g.Key == 0) return (recentOrder, 1, "", (int)g.Key); |
| 68 | var si = lookupStore(g.Key); |
| 69 | if (si != null && !string.IsNullOrEmpty(si.Name)) |
| 70 | return (recentOrder, 0, si.Name, (int)g.Key); |
| 71 | return (recentOrder, 0, "", (int)g.Key); |
| 72 | }).ToList(); |
| 73 | |
| 74 | foreach (var group in sortedGroups) |
| 75 | { |
| 76 | uint appId = group.Key; |
| 77 | var sorted = group.Value.OrderByDescending(b => b.Timestamp).ToList(); |
| 78 | |
| 79 | // Resolve game name + icon URL |
| 80 | var storeInfo = appId != 0 ? lookupStore(appId) : null; |
| 81 | string gameName = appId == 0 ? S.Get("Backup_UnknownApp") : |
| 82 | (storeInfo != null && !string.IsNullOrEmpty(storeInfo.Name) |
| 83 | ? storeInfo.Name : S.Format("Apps_AppFallbackName", appId)); |
| 84 | string? headerUrl = storeInfo?.HeaderUrl; |
| 85 | |
| 86 | // Game card |
| 87 | var card = new Border |
no test coverage detected