Skip to content

Commit 7f52619

Browse files
authored
Merge pull request #3338 from mrixner/remove-all-desktop-shortcuts
'Automatically Remove All Desktop Shortcuts' Option
2 parents 35237fc + aa236e1 commit 7f52619

File tree

5 files changed

+219
-167
lines changed

5 files changed

+219
-167
lines changed

src/UniGetUI.PackageEngine.Operations/PackageOperations.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ protected override Task HandleSuccess()
157157

158158
if (Settings.Get("AskToDeleteNewDesktopShortcuts"))
159159
{
160-
DesktopShortcutsDatabase.TryRemoveNewShortcuts(DesktopShortcutsBeforeStart);
160+
DesktopShortcutsDatabase.HandleNewShortcuts(DesktopShortcutsBeforeStart);
161161
}
162162
return Task.CompletedTask;
163163
}
@@ -177,7 +177,7 @@ protected override void Initialize()
177177

178178
if (Settings.Get("AskToDeleteNewDesktopShortcuts"))
179179
{
180-
DesktopShortcutsBeforeStart = DesktopShortcutsDatabase.GetShortcuts();
180+
DesktopShortcutsBeforeStart = DesktopShortcutsDatabase.GetShortcutsOnDisk();
181181
}
182182
}
183183
}
@@ -209,7 +209,7 @@ protected override async Task HandleSuccess()
209209

210210
if (Settings.Get("AskToDeleteNewDesktopShortcuts"))
211211
{
212-
DesktopShortcutsDatabase.TryRemoveNewShortcuts(DesktopShortcutsBeforeStart);
212+
DesktopShortcutsDatabase.HandleNewShortcuts(DesktopShortcutsBeforeStart);
213213
}
214214

215215
if (await Package.HasUpdatesIgnoredAsync() && await Package.GetIgnoredUpdatesVersionAsync() != "*")
@@ -231,7 +231,7 @@ protected override void Initialize()
231231

232232
if (Settings.Get("AskToDeleteNewDesktopShortcuts"))
233233
{
234-
DesktopShortcutsBeforeStart = DesktopShortcutsDatabase.GetShortcuts();
234+
DesktopShortcutsBeforeStart = DesktopShortcutsDatabase.GetShortcutsOnDisk();
235235
}
236236
}
237237
}

src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/DesktopShortcutsDatabase.cs

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ public static class DesktopShortcutsDatabase
88
public enum Status
99
{
1010
Maintain, // The user has explicitly requested this shortcut not be deleted
11-
Delete, // The user has allowed the shortcut to be deleted
1211
Unknown, // The user has not said whether they want this shortcut to be deleted
12+
Delete, // The user has allowed the shortcut to be deleted
1313
}
1414

1515
private static readonly List<string> UnknownShortcuts = [];
@@ -28,10 +28,13 @@ public static void ResetDatabase()
2828
/// Adds a desktop shortcut to the deletable desktop shortcuts database
2929
/// </summary>
3030
/// <param name="shortcutPath">The path of the shortcut to delete</param>
31-
/// <param name="deletable">Whether or not to mark this entry as deletable in the database. Defaults to true</param>
32-
public static void AddToDatabase(string shortcutPath, bool deletable = true)
31+
/// <param name="shortcutStatus">The status to set</param>
32+
public static void AddToDatabase(string shortcutPath, Status shortcutStatus)
3333
{
34-
Settings.SetDictionaryItem("DeletableDesktopShortcuts", shortcutPath, deletable);
34+
if (shortcutStatus is Status.Unknown)
35+
Settings.RemoveDictionaryKey<string, bool>("DeletableDesktopShortcuts", shortcutPath);
36+
else
37+
Settings.SetDictionaryItem<string, bool>("DeletableDesktopShortcuts", shortcutPath, shortcutStatus is Status.Delete);
3538
}
3639

3740
/// <summary>
@@ -54,28 +57,6 @@ public static bool Remove(string shortcutPath)
5457
return false;
5558
}
5659

57-
/// <summary>
58-
/// Attempts to reset the configuration of a given shortcut path from the database.
59-
/// This will make it so the user is asked about it the next time it is discovered.
60-
/// Different from `Remove` as Remove simply marks it as non-deletable, whereas this removes the configuration entirely.
61-
/// </summary>
62-
/// <param name="shortcutPath">The path of the shortcut to delete</param>
63-
/// <returns>True if the shortcut was completely removed, false if it was not there from the beginning</returns>
64-
public static bool ResetShortcut(string shortcutPath)
65-
{
66-
// Remove the entry if present
67-
if (Settings.DictionaryContainsKey<string, bool>("DeletableDesktopShortcuts", shortcutPath))
68-
{
69-
// Remove the entry and propagate changes to disk
70-
Settings.RemoveDictionaryKey<string, bool>("DeletableDesktopShortcuts", shortcutPath);
71-
return true;
72-
}
73-
74-
// Do nothing if the entry was not there
75-
Logger.Warn($"Attempted to reset a deletable desktop shortcut {{shortcutPath={shortcutPath}}} that was not found there");
76-
return false;
77-
}
78-
7960
/// <summary>
8061
/// Attempts to delete the given shortcut path off the disk
8162
/// </summary>
@@ -103,7 +84,7 @@ public static bool DeleteFromDisk(string shortcutPath)
10384
/// until a choice is given to the user and they explicitly request that it be deleted.
10485
/// </summary>
10586
/// <param name="shortcutPath">The path of the shortcut to be deleted</param>
106-
/// <returns>True if the package is ignored, false otherwhise</returns>
87+
/// <returns>The status of a shortcut</returns>
10788
public static Status GetStatus(string shortcutPath)
10889
{
10990
// Check if the package is ignored
@@ -120,7 +101,7 @@ public static Status GetStatus(string shortcutPath)
120101
/// Get a list of shortcuts (.lnk files only) currently on the user's desktop
121102
/// </summary>
122103
/// <returns>A list of desktop shortcut paths</returns>
123-
public static List<string> GetShortcuts()
104+
public static List<string> GetShortcutsOnDisk()
124105
{
125106
List<string> shortcuts = [];
126107
string UserDesktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
@@ -130,6 +111,23 @@ public static List<string> GetShortcuts()
130111
return shortcuts;
131112
}
132113

114+
/// <summary>
115+
/// Gets all the shortcuts exist on disk or/and on the database
116+
/// </summary>
117+
/// <returns></returns>
118+
public static List<string> GetAllShortcuts()
119+
{
120+
var shortcuts = GetShortcutsOnDisk();
121+
122+
foreach (var item in Settings.GetDictionary<string, bool>("DeletableDesktopShortcuts"))
123+
{
124+
if (!shortcuts.Contains(item.Key))
125+
shortcuts.Add(item.Key);
126+
}
127+
128+
return shortcuts;
129+
}
130+
133131
/// <summary>
134132
/// Remove a shortcut from the list of shortcuts whose deletion verdicts are unknown (as in, the user needs to be asked about deleting them when their operations finish)
135133
/// </summary>
@@ -150,29 +148,52 @@ public static List<string> GetUnknownShortcuts()
150148
}
151149

152150
/// <summary>
153-
/// Will attempt to remove new desktop shortcuts, if applicable.
151+
/// Will handle the removal, if applicable, of any shortcut that is not present on the given PreviousShortCutList.
154152
/// </summary>
155-
/// <param name="PreviousShortCutList"></param>
156-
public static void TryRemoveNewShortcuts(IReadOnlyList<string> PreviousShortCutList)
153+
/// <param name="PreviousShortCutList">The shortcuts that already existed</param>
154+
public static void HandleNewShortcuts(IReadOnlyList<string> PreviousShortCutList)
157155
{
158-
HashSet<string> ShortcutSet = PreviousShortCutList.ToHashSet();
159-
List<string> CurrentShortcutList = DesktopShortcutsDatabase.GetShortcuts();
160-
foreach (string shortcut in CurrentShortcutList)
156+
bool DeleteUnknownShortcuts = Settings.Get("RemoveAllDesktopShortcuts");
157+
HashSet<string> PreviousShortcuts = [.. PreviousShortCutList];
158+
List<string> CurrentShortcuts = GetShortcutsOnDisk();
159+
160+
foreach (string shortcut in CurrentShortcuts)
161161
{
162-
if (ShortcutSet.Contains(shortcut)) continue;
163-
switch (DesktopShortcutsDatabase.GetStatus(shortcut))
162+
var status = GetStatus(shortcut);
163+
if (status is Status.Maintain)
164+
{
165+
// Don't delete this shortcut, it has been set to be kept
166+
}
167+
else if (status is Status.Delete)
168+
{
169+
// If a shortcut is set to be deleted, delete it,
170+
// even when it was not created during an UniGetUI operation
171+
DeleteFromDisk(shortcut);
172+
}
173+
else if (status is Status.Unknown)
164174
{
165-
case Status.Delete:
166-
DesktopShortcutsDatabase.DeleteFromDisk(shortcut);
167-
break;
168-
case Status.Maintain:
169-
Logger.Debug("Refraining from deleting new shortcut " + shortcut + ": user disabled its deletion");
170-
break;
171-
case Status.Unknown:
172-
if (UnknownShortcuts.Contains(shortcut)) continue;
173-
Logger.Info("Marking the shortcut " + shortcut + " to be asked to be deleted");
174-
UnknownShortcuts.Add(shortcut);
175-
break;
175+
if (DeleteUnknownShortcuts)
176+
{
177+
// If a shortcut has not been detected yet, and it
178+
// existed before an operation started, then do nothing.
179+
if(PreviousShortcuts.Contains(shortcut))
180+
continue;
181+
182+
// If the shortcut was created during an operation
183+
// and autodelete is enabled, delete that icon
184+
Logger.Warn($"New shortcut {shortcut} will be set for deletion (this shortcut was never seen before)");
185+
AddToDatabase(shortcut, Status.Delete);
186+
DeleteFromDisk(shortcut);
187+
}
188+
else
189+
{
190+
// Mark the shortcut as unknown and prompt the user.
191+
if (!UnknownShortcuts.Contains(shortcut))
192+
{
193+
Logger.Info($"Marking the shortcut {shortcut} to be asked to be deleted");
194+
UnknownShortcuts.Add(shortcut);
195+
}
196+
}
176197
}
177198
}
178199
}

src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
xmlns:local="using:UniGetUI.Interface"
88
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
99
xmlns:widgets="using:UniGetUI.Interface.Widgets"
10-
Width="900"
11-
MaxWidth="1100"
10+
MaxWidth="950"
1211
mc:Ignorable="d">
1312

1413
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
@@ -30,7 +29,7 @@
3029
VerticalAlignment="Bottom"
3130
Orientation="Vertical"
3231
Spacing="4">
33-
<Button Margin="10,0,0,0" HorizontalAlignment="Stretch">
32+
<!--Button Margin="10,0,0,0" HorizontalAlignment="Stretch">
3433
<widgets:TranslatedTextBlock Text="Manual scan" />
3534
<Button.Flyout>
3635
<Flyout
@@ -49,11 +48,11 @@
4948
<ColumnDefinition Width="*" />
5049
<ColumnDefinition Width="*" />
5150
</Grid.ColumnDefinitions>
52-
<TextBlock
51+
<widgets:TranslatedTextBlock
5352
Grid.ColumnSpan="2"
5453
Margin="0,0,0,0"
5554
Text="Existing shortcuts on your desktop will be scanned, and you will need to pick which ones to keep and which ones to remove."
56-
TextWrapping="WrapWholeWords" />
55+
WrappingMode="WrapWholeWords" />
5756
<Button
5857
Grid.Row="1"
5958
Grid.Column="1"
@@ -65,7 +64,7 @@
6564
</Grid>
6665
</Flyout>
6766
</Button.Flyout>
68-
</Button>
67+
</Button-->
6968
<Button Margin="10,0,0,0" HorizontalAlignment="Stretch">
7069
<widgets:TranslatedTextBlock Text="Reset list" />
7170
<Button.Flyout>
@@ -85,11 +84,11 @@
8584
<ColumnDefinition Width="*" />
8685
<ColumnDefinition Width="*" />
8786
</Grid.ColumnDefinitions>
88-
<TextBlock
87+
<widgets:TranslatedTextBlock
8988
Grid.ColumnSpan="2"
9089
Margin="0,0,0,0"
9190
Text="Do you really want to reset this list? This action cannot be reverted."
92-
TextWrapping="WrapWholeWords" />
91+
WrappingMode="WrapWholeWords" />
9392
<Button
9493
Grid.Row="1"
9594
Grid.Column="1"
@@ -115,56 +114,83 @@
115114
<ListView
116115
Name="DeletableDesktopShortcutsList"
117116
Height="350"
118-
Padding="2,4,2,4"
117+
Padding="0,4,2,4"
119118
HorizontalAlignment="Stretch"
120119
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
121120
CornerRadius="6"
122-
DoubleTapped="DeletableDesktopShortcutsList_DoubleTapped">
121+
ItemsSource="{x:Bind Shortcuts}">
123122
<ListView.ItemTemplate>
124123
<DataTemplate x:DataType="local:ShortcutEntry">
125-
<Grid ColumnSpacing="4">
124+
<Grid Margin="-4,2,0,2" ColumnSpacing="4">
126125
<Grid.ColumnDefinitions>
127-
<ColumnDefinition Width="50" />
126+
<ColumnDefinition Width="Auto" />
127+
<ColumnDefinition Width="2" />
128+
<ColumnDefinition Width="24" />
129+
<ColumnDefinition Width="*" MaxWidth="200" />
128130
<ColumnDefinition Width="24" />
129131
<ColumnDefinition Width="*" />
130132
<ColumnDefinition Width="Auto" />
131133
<ColumnDefinition Width="Auto" />
132134
</Grid.ColumnDefinitions>
133-
<CheckBox Grid.Column="0" IsChecked="{x:Bind IsChecked, Mode=TwoWay}" />
135+
<Border
136+
Grid.Column="0"
137+
Width="20"
138+
HorizontalAlignment="Center">
139+
<CheckBox
140+
MaxWidth="10"
141+
Margin="0,8,0,0"
142+
IsChecked="{x:Bind IsDeletable, Mode=TwoWay}" />
143+
</Border>
144+
<widgets:TranslatedTextBlock
145+
Grid.Column="0"
146+
HorizontalAlignment="Center"
147+
VerticalAlignment="Top"
148+
FontSize="10"
149+
Text="Delete?" />
134150
<FontIcon
135-
Grid.Column="1"
151+
Grid.Column="2"
136152
Width="24"
137153
Height="24"
138154
Glyph="&#xECAA;" />
139155
<TextBlock
140-
Grid.Column="2"
156+
Grid.Column="3"
141157
VerticalAlignment="Center"
142-
Text="{x:Bind ShortcutPath}" />
158+
Text="{x:Bind Name}" />
159+
<FontIcon
160+
Grid.Column="4"
161+
Width="24"
162+
Height="24"
163+
Glyph="&#xE71B;" />
164+
<TextBlock
165+
Grid.Column="5"
166+
VerticalAlignment="Center"
167+
Text="{x:Bind Path}" />
143168
<Button
144-
Grid.Column="3"
169+
Grid.Column="6"
145170
Width="32"
146171
Height="32"
147172
Padding="0"
148173
Click="{x:Bind OpenShortcutPath}"
149-
IsEnabled="{x:Bind ShortcutExists}">
174+
IsEnabled="{x:Bind ExistsOnDisk}">
150175
<widgets:LocalIcon
151176
Width="24"
152177
Height="24"
153178
Icon="launch" />
154179
</Button>
155180
<Button
156-
Grid.Column="4"
181+
Grid.Column="7"
157182
Width="32"
158183
Height="32"
159184
Padding="0"
160-
Click="{x:Bind ResetConfiguration}">
185+
Click="{x:Bind ResetShortcut}">
161186
<FontIcon FontSize="16" Glyph="&#xE74D;" />
162187
</Button>
163188
</Grid>
164189
</DataTemplate>
165190
</ListView.ItemTemplate>
166191
</ListView>
167192
</ScrollViewer>
193+
<CheckBox Name="AutoDeleteShortcutsCheckbox" Content="When new shortcuts are detected, delete them automatically instead of showing this dialog." />
168194
</StackPanel>
169195
<!-- Close Button -->
170196
<widgets:DialogCloseButton Margin="0,-63,-24,0" Click="CloseButton_Click" />

0 commit comments

Comments
 (0)