Skip to content

Commit 6348864

Browse files
authored
Merge pull request #607 from TheJoeFin/copilot/sub-pr-606
Refactor post-grab actions: fix memory leaks, improve performance, enhance maintainability
2 parents 9b7c63e + 481aad0 commit 6348864

File tree

3 files changed

+71
-26
lines changed

3 files changed

+71
-26
lines changed

Text-Grab/Models/ButtonInfo.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,15 @@ public override bool Equals(object? obj)
4343

4444
public override int GetHashCode()
4545
{
46-
return System.HashCode.Combine(ButtonText, SymbolText, Background, Command, ClickEvent, IsRelevantForFullscreenGrab, IsRelevantForEditWindow);
46+
return System.HashCode.Combine(
47+
ButtonText,
48+
SymbolText,
49+
Background,
50+
Command,
51+
ClickEvent,
52+
IsRelevantForFullscreenGrab,
53+
IsRelevantForEditWindow,
54+
DefaultCheckState);
4755
}
4856

4957
// a constructor which takes a collapsible button

Text-Grab/Utilities/PostGrabActionManager.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,10 @@ public static List<ButtonInfo> GetAvailablePostGrabActions()
2222
List<ButtonInfo> allPostGrabActions = [.. GetDefaultPostGrabActions()];
2323

2424
// Add other relevant actions from AllButtons that are marked as relevant for FullscreenGrab
25-
foreach (ButtonInfo button in ButtonInfo.AllButtons)
26-
{
27-
if (button.IsRelevantForFullscreenGrab && !allPostGrabActions.Any(b => b.ButtonText == button.ButtonText))
28-
{
29-
allPostGrabActions.Add(button);
30-
}
31-
}
25+
IEnumerable<ButtonInfo> relevantActions = ButtonInfo.AllButtons
26+
.Where(button => button.IsRelevantForFullscreenGrab && !allPostGrabActions.Any(b => b.ButtonText == button.ButtonText));
27+
28+
allPostGrabActions.AddRange(relevantActions);
3229

3330
return [.. allPostGrabActions.OrderBy(b => b.OrderNumber)];
3431
}
@@ -144,11 +141,12 @@ public static bool GetCheckState(ButtonInfo action)
144141
try
145142
{
146143
Dictionary<string, bool>? checkStates = JsonSerializer.Deserialize<Dictionary<string, bool>>(statesJson);
147-
if (checkStates is not null && checkStates.TryGetValue(action.ButtonText, out bool storedState))
144+
if (checkStates is not null
145+
&& checkStates.TryGetValue(action.ButtonText, out bool storedState)
146+
&& action.DefaultCheckState == DefaultCheckState.LastUsed)
148147
{
149148
// If the action is set to LastUsed, use the stored state
150-
if (action.DefaultCheckState == DefaultCheckState.LastUsed)
151-
return storedState;
149+
return storedState;
152150
}
153151
}
154152
catch (JsonException)
@@ -202,11 +200,14 @@ public static async Task<string> ExecutePostGrabAction(ButtonInfo action, string
202200

203201
case "TrimEachLine_Click":
204202
string[] stringSplit = text.Split(Environment.NewLine);
205-
string finalString = "";
206-
foreach (string line in stringSplit)
207-
if (!string.IsNullOrWhiteSpace(line))
208-
finalString += line.Trim() + Environment.NewLine;
209-
result = finalString;
203+
string[] trimmedLines = stringSplit
204+
.Where(line => !string.IsNullOrWhiteSpace(line))
205+
.Select(line => line.Trim())
206+
.ToArray();
207+
208+
result = trimmedLines.Length == 0
209+
? string.Empty
210+
: string.Join(Environment.NewLine, trimmedLines) + Environment.NewLine;
210211
break;
211212

212213
case "RemoveDuplicateLines_Click":

Text-Grab/Views/FullscreenGrab.xaml.cs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public partial class FullscreenGrab : Window
4848
private const double MaxZoomScale = 16.0;
4949
private const double EdgePanThresholdPercent = 0.10;
5050
private const double EdgePanSpeed = 8.0;
51+
private const string EditPostGrabActionsTag = "EditPostGrabActions";
52+
private const string ClosePostGrabMenuTag = "ClosePostGrabMenu";
5153
private readonly DispatcherTimer edgePanTimer;
5254

5355
#endregion Fields
@@ -270,6 +272,12 @@ private void LoadDynamicPostGrabActions()
270272
// Get the PostGrabStayOpen setting
271273
bool stayOpen = DefaultSettings.PostGrabStayOpen;
272274

275+
// Remove any existing keyboard handler to avoid duplicates
276+
contextMenu.PreviewKeyDown -= FullscreenGrab_KeyDown;
277+
278+
// Add keyboard handling once for the entire context menu
279+
contextMenu.PreviewKeyDown += FullscreenGrab_KeyDown;
280+
273281
int index = 1;
274282
foreach (ButtonInfo action in enabledActions)
275283
{
@@ -286,9 +294,6 @@ private void LoadDynamicPostGrabActions()
286294
// Wire up click handler
287295
menuItem.Click += PostActionMenuItem_Click;
288296

289-
// Add keyboard handling
290-
contextMenu.PreviewKeyDown += FullscreenGrab_KeyDown;
291-
292297
contextMenu.Items.Add(menuItem);
293298
index++;
294299
}
@@ -298,15 +303,17 @@ private void LoadDynamicPostGrabActions()
298303
// Add "Edit this list..." menu item
299304
MenuItem editPostGrabMenuItem = new()
300305
{
301-
Header = "Edit this list..."
306+
Header = "Edit this list...",
307+
Tag = EditPostGrabActionsTag
302308
};
303309
editPostGrabMenuItem.Click += EditPostGrabActions_Click;
304310
contextMenu.Items.Add(editPostGrabMenuItem);
305311

306312
// Add "Close this menu" menu item
307313
MenuItem hidePostGrabMenuItem = new()
308314
{
309-
Header = "Close this menu"
315+
Header = "Close this menu",
316+
Tag = ClosePostGrabMenuTag
310317
};
311318
hidePostGrabMenuItem.Click += HidePostGrabActions_Click;
312319
contextMenu.Items.Add(hidePostGrabMenuItem);
@@ -1010,6 +1017,36 @@ private void Window_Unloaded(object sender, RoutedEventArgs e)
10101017
if (RegionClickCanvas.Children.Contains(selectBorder))
10111018
RegionClickCanvas.Children.Remove(selectBorder);
10121019

1020+
// Clean up dynamically created post-grab action menu items
1021+
if (NextStepDropDownButton.Flyout is ContextMenu contextMenu)
1022+
{
1023+
contextMenu.PreviewKeyDown -= FullscreenGrab_KeyDown;
1024+
1025+
foreach (object item in contextMenu.Items)
1026+
{
1027+
if (item is MenuItem menuItem)
1028+
{
1029+
if (menuItem.Tag is ButtonInfo)
1030+
{
1031+
menuItem.Click -= PostActionMenuItem_Click;
1032+
}
1033+
else if (menuItem.Tag is string tag)
1034+
{
1035+
if (tag == EditPostGrabActionsTag)
1036+
{
1037+
menuItem.Click -= EditPostGrabActions_Click;
1038+
}
1039+
else if (tag == ClosePostGrabMenuTag)
1040+
{
1041+
menuItem.Click -= HidePostGrabActions_Click;
1042+
}
1043+
}
1044+
}
1045+
}
1046+
1047+
contextMenu.Items.Clear();
1048+
}
1049+
10131050
CurrentScreen = null;
10141051
dpiScale = null;
10151052
TextFromOCR = null;
@@ -1100,12 +1137,11 @@ private void TableToggleButton_Click(object? sender = null, RoutedEventArgs? e =
11001137
private void PostActionMenuItem_Click(object sender, RoutedEventArgs e)
11011138
{
11021139
// Save check state for LastUsed tracking
1103-
if (sender is MenuItem menuItem && menuItem.Tag is ButtonInfo action)
1140+
if (sender is MenuItem menuItem
1141+
&& menuItem.Tag is ButtonInfo action
1142+
&& action.DefaultCheckState == DefaultCheckState.LastUsed)
11041143
{
1105-
if (action.DefaultCheckState == DefaultCheckState.LastUsed)
1106-
{
1107-
PostGrabActionManager.SaveCheckState(action, menuItem.IsChecked);
1108-
}
1144+
PostGrabActionManager.SaveCheckState(action, menuItem.IsChecked);
11091145
}
11101146

11111147
CheckIfAnyPostActionsSelected();

0 commit comments

Comments
 (0)