Skip to content

Commit 3df5115

Browse files
committed
Fix async icon loading in timeline and preview: subscribe to IconLoaded event in HistoryViewController and TimelinePreviewManager to refresh UI when app/site icons finish loading, ensuring icons appear without manual scrolling. You can now expand Explorer to filter screenshots by a specific folder.
1 parent 55ff050 commit 3df5115

5 files changed

Lines changed: 96 additions & 7 deletions

File tree

Recap/Resources/AppFilterController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public class AppFilterController : IDisposable
6363
"browser.exe",
6464
"firefox.exe",
6565
"telegram.exe", "ayugram.exe", "kotatogram.exe", "64gram.exe",
66-
"code.exe", "devenv.exe", "antigravity.exe"
66+
"code.exe", "devenv.exe", "antigravity.exe", "explorer.exe"
6767
};
6868

6969
private readonly HashSet<string> _messengers = new HashSet<string>(StringComparer.OrdinalIgnoreCase)

Recap/Resources/HistoryViewController.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public HistoryViewController(
100100
_ocrDb = ocrDb;
101101
_txtOcrSearch = txtOcrSearch;
102102
_iconManager = iconManager;
103+
_iconManager.IconLoaded += OnIconLoaded;
103104

104105
_dataManager = new TimelineDataManager(frameRepository, ocrDb, settings);
105106
_mediaController = new MediaPlayerController(libVLC, mediaPlayer);
@@ -400,6 +401,40 @@ private async void OnSearchKeyDown(object sender, KeyEventArgs e)
400401
}
401402
}
402403

404+
private void OnIconLoaded(string loadedAppName)
405+
{
406+
if (_mainPictureBox.InvokeRequired)
407+
{
408+
_mainPictureBox.BeginInvoke(new Action(() => OnIconLoaded(loadedAppName)));
409+
return;
410+
}
411+
412+
if (_currentFrameIndex >= 0 && _dataManager.FilteredFrames != null && _currentFrameIndex < _dataManager.FilteredFrames.Count)
413+
{
414+
var currentFrame = _dataManager.FilteredFrames[_currentFrameIndex];
415+
string rawAppName = "";
416+
if (_dataManager.AppMap.TryGetValue(currentFrame.AppId, out string name))
417+
{
418+
rawAppName = name;
419+
}
420+
else
421+
{
422+
var frameData = _frameRepository.GetFrameIndex(currentFrame.TimestampTicks);
423+
if (frameData.TimestampTicks != 0)
424+
{
425+
rawAppName = frameData.AppName;
426+
}
427+
}
428+
429+
if (string.Equals(rawAppName, loadedAppName, StringComparison.OrdinalIgnoreCase))
430+
{
431+
Image appIcon = _iconManager.GetIcon(rawAppName);
432+
string cleanName = CleanAppNameForUI(rawAppName);
433+
_timelineController.UpdateCurrentApp(cleanName, appIcon);
434+
}
435+
}
436+
}
437+
403438
private void OnUiTimerTick(object sender, EventArgs e)
404439
{
405440
if (_wantedFrameIndex != -1 && _wantedFrameIndex != _currentFrameIndex)
@@ -988,6 +1023,11 @@ public void UpdateSettings(AppSettings newSettings, FrameRepository newFrameRepo
9881023

9891024
public void Dispose()
9901025
{
1026+
if (_iconManager != null)
1027+
{
1028+
_iconManager.IconLoaded -= OnIconLoaded;
1029+
}
1030+
9911031
FrameChanged = null;
9921032
CurrentDateChanged = null;
9931033
OcrBlacklistToggled = null;

Recap/Resources/IconManager.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ public Image GetIcon(string rawAppName)
106106
IconType type = IconType.Exe;
107107
string payload = exeName;
108108

109-
if (lowerExe.Contains("code.exe") || lowerExe.Contains("devenv.exe") ||
110-
lowerExe.Contains("code") || lowerExe.Contains("visualstudio") || lowerExe.Contains("antigravity"))
109+
if (lowerExe.Contains("code.exe") || lowerExe.Contains("devenv.exe") ||
110+
lowerExe.Contains("code") || lowerExe.Contains("visualstudio") || lowerExe.Contains("antigravity") || lowerExe.Contains("explorer"))
111111
{
112112
cacheKey = "exe_" + MakeSafeFilename(exeName).ToLower();
113113
type = IconType.Exe;
@@ -432,12 +432,12 @@ private string GetCacheKey(string rawAppName)
432432
string exeName = parts[0];
433433
string lowerExe = exeName.ToLower();
434434

435-
if (lowerExe.Contains("code.exe") || lowerExe.Contains("devenv.exe") ||
436-
lowerExe.Contains("code") || lowerExe.Contains("visualstudio") || lowerExe.Contains("antigravity"))
435+
if (lowerExe.Contains("code.exe") || lowerExe.Contains("devenv.exe") ||
436+
lowerExe.Contains("code") || lowerExe.Contains("visualstudio") || lowerExe.Contains("antigravity") || lowerExe.Contains("explorer"))
437437
{
438438
return "exe_" + MakeSafeFilename(exeName).ToLower();
439439
}
440-
440+
441441
if (lowerExe.Contains("telegram") || lowerExe.Contains("ayugram") || lowerExe.Contains("kotatogram"))
442442
{
443443
return "exe_" + MakeSafeFilename(exeName).ToLower();

Recap/Resources/TimelinePreviewManager.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,38 @@ public void ReloadAliases()
2626
private bool _isWorkerRunning = false;
2727
private readonly object _workerLock = new object();
2828
private Dictionary<string, string> _aliases = new Dictionary<string, string>();
29+
private string _currentPreviewAppName = "";
2930

3031
public TimelinePreviewManager(FrameRepository frameRepository, IconManager iconManager)
3132
{
3233
_frameRepository = frameRepository;
3334
_iconManager = iconManager;
3435
_aliases = _frameRepository.GetAliases();
3536
_previewPopup = new PreviewPopup(PreviewWidth, PreviewHeight);
37+
_iconManager.IconLoaded += OnIconLoaded;
38+
}
39+
40+
private void OnIconLoaded(string name)
41+
{
42+
if (string.Equals(_currentPreviewAppName, name, StringComparison.OrdinalIgnoreCase))
43+
{
44+
var newIcon = _iconManager.GetIcon(name);
45+
if (!_previewPopup.IsDisposed)
46+
{
47+
if (_previewPopup.InvokeRequired)
48+
{
49+
_previewPopup.BeginInvoke(new Action(() =>
50+
{
51+
if (!_previewPopup.IsDisposed)
52+
_previewPopup.UpdateIcon(newIcon);
53+
}));
54+
}
55+
else
56+
{
57+
_previewPopup.UpdateIcon(newIcon);
58+
}
59+
}
60+
}
3661
}
3762

3863
public void Show(MiniFrame frame, Control trackBar, int mouseX)
@@ -121,6 +146,7 @@ private async Task ProcessQueueAsync()
121146
return;
122147
}
123148

149+
_currentPreviewAppName = currentFrame.AppName;
124150
Image icon = _iconManager.GetIcon(currentFrame.AppName);
125151

126152
string timeStr = currentFrame.GetTime().ToString("HH:mm:ss");
@@ -279,6 +305,10 @@ private Point CalculatePopupPosition(Control trackBar, int mouseX)
279305

280306
public void Dispose()
281307
{
308+
if (_iconManager != null)
309+
{
310+
_iconManager.IconLoaded -= OnIconLoaded;
311+
}
282312
lock (_workerLock) { _nextFrameToLoad = null; }
283313
if (!_previewPopup.IsDisposed)
284314
{
@@ -318,7 +348,12 @@ public void ShowInactive()
318348

319349
[System.Runtime.InteropServices.DllImport("user32.dll")]
320350
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
321-
351+
public void UpdateIcon(Image icon)
352+
{
353+
if (this.IsDisposed) return;
354+
_appIcon = icon;
355+
this.Invalidate();
356+
}
322357
public void UpdateContent(Image image, Image icon, string text, string timeStr)
323358
{
324359
if (this.IsDisposed) return;

Recap/Utilities/AppNameParser.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,20 @@ public static string ParseWindowName(string processName, string domain, string t
136136
return $"{processName}|{chatName}";
137137
}
138138
}
139+
else if (procLower.Contains("explorer"))
140+
{
141+
if (!string.IsNullOrEmpty(title) && title != "Program Manager")
142+
{
143+
string[] explorerSuffixes = {
144+
" - Проводник", " – Проводник", " — Проводник",
145+
" - File Explorer", " – File Explorer", " — File Explorer",
146+
" - Windows Explorer", " – Windows Explorer", " — Windows Explorer",
147+
" - Explorer", " – Explorer", " — Explorer"
148+
};
149+
string cleanTitle = CleanupTitle(title, explorerSuffixes);
150+
return $"{processName}|{cleanTitle}";
151+
}
152+
}
139153

140154
return processName;
141155
}

0 commit comments

Comments
 (0)