Skip to content

Allow Desktop Shortcut Deletion #2985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
791be5e
Add the deletable desktop shortcuts database
mrixner Nov 16, 2024
a57bffb
Add a function to get a list of shortcuts on the desktop
mrixner Nov 16, 2024
7781e73
Add the 'ask to delete new desktop shortcuts' setting
mrixner Nov 16, 2024
918cb9a
Fix formatting
mrixner Nov 23, 2024
acd0dc4
Avoid random System.NullReferenceException: 'Object reference not set…
mrixner Nov 24, 2024
15270d1
Add the actual shortcut deletion functionality
mrixner Nov 24, 2024
7c2693b
Change the name of the new desktop shortcuts listview
mrixner Nov 24, 2024
8eb40ec
Add a ResetDatabase function to the desktop shortcuts database
mrixner Nov 24, 2024
237952d
Add a `Reset` option to the shortcuts database
mrixner Nov 24, 2024
ca0d34c
Fix formatting
mrixner Nov 25, 2024
d0b9c7e
Allow shortcuts to be added as undeletable
mrixner Nov 25, 2024
5fb3583
Remove unneeded Grid.Column property
mrixner Nov 25, 2024
5473d2f
Allow for the management of existing desktop shortcut rules
mrixner Nov 25, 2024
1b8624c
Add notifications when a new desktop shortcut is detected
mrixner Nov 25, 2024
ba6ac6d
Merge branch main into delete-desktop-shortcuts
mrixner Nov 25, 2024
9d81299
Merge branch 'main' into delete-desktop-shortcuts
marticliment Nov 26, 2024
dfbacaa
Revert column definitions
mrixner Nov 26, 2024
6249ab4
Merge branch 'main' into delete-desktop-shortcuts
mrixner Dec 1, 2024
fdca728
Port the deletable desktop shortcuts database to the new complex sett…
mrixner Dec 1, 2024
ef83ac3
Delete desktop shortcuts on installation as well
mrixner Dec 1, 2024
35032dc
Revert commit that will be fixed by marticliment later (and better).
mrixner Dec 1, 2024
cd63431
Remove now unused CoreData.IgnoredUpdatesDatabaseFile
marticliment Dec 3, 2024
e8dd9d1
Merge branch 'main' into pr/2985
marticliment Dec 3, 2024
a665bee
Run shortcut manager on install operation also, move code block to De…
marticliment Dec 3, 2024
9e4ad52
Simplify some methods names, minor code changes
marticliment Dec 3, 2024
1232867
Fuse ShortcutManager and NewShortcutManager into one single dialog, A…
marticliment Dec 3, 2024
3342ede
Minor improvements
marticliment Dec 3, 2024
d46f3e2
fix duplicated icon
marticliment Dec 7, 2024
ed9937b
Merge branch 'main' into delete-desktop-shortcuts
marticliment Dec 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/UniGetUI.Core.Settings/SettingsEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ public static bool AreUpdatesNotificationsDisabled()
return AreNotificationsDisabled() || Get("DisableUpdatesNotifications");
}

public static bool AreShortcutsNotificationsDisabled()
/*public static bool AreShortcutsNotificationsDisabled()
{
return AreNotificationsDisabled() || Get("DisableShortcutNotifications");
}
}*/

public static bool AreErrorNotificationsDisabled()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void ResetDatabase()
/// </summary>
/// <param name="shortcutPath">The path of the shortcut to delete</param>
/// <param name="deletable">Whether or not to mark this entry as deletable in the databse. Defaults to true</param>
public static void Add(string shortcutPath, bool deletable = true)
public static void AddToDatabase(string shortcutPath, bool deletable = true)
{
Settings.SetDictionaryItem("DeletableDesktopShortcuts", shortcutPath, deletable);
}
Expand Down Expand Up @@ -67,7 +67,7 @@ public static bool Remove(string shortcutPath)
/// </summary>
/// <param name="shortcutPath">The path of the shortcut to delete</param>
/// <returns>True if the shortcut was completely removed, false if it was not there from the beginning</returns>
public static bool Reset(string shortcutPath)
public static bool ResetShortcut(string shortcutPath)
{
// Remove the entry if present
if (Settings.DictionaryContainsKey<string, bool>("DeletableDesktopShortcuts", shortcutPath))
Expand All @@ -89,7 +89,7 @@ public static bool Reset(string shortcutPath)
/// </summary>
/// <param name="shortcutPath">The path of the shortcut to delete</param>
/// <returns>True if the shortcut was deleted, false if it was not (or didn't exist)</returns>
public static bool DeleteShortcut(string shortcutPath)
public static bool DeleteFromDisk(string shortcutPath)
{
Logger.Info("Deleting shortcut " + shortcutPath);
try
Expand Down Expand Up @@ -132,8 +132,21 @@ public static Status GetStatus(string shortcutPath)
/// <returns>A list of desktop shortcut paths</returns>
public static List<string> GetShortcuts()
{
string DesktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
return Directory.EnumerateFiles(DesktopPath, "*.lnk").ToList();
string UserDesktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
string CommonDesktop = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory);
List<string> shortcuts = new();

foreach (var shortcut in Directory.EnumerateFiles(UserDesktop, "*.lnk"))
{
shortcuts.Add(Path.Join(UserDesktop, shortcut));
}

foreach (var shortcut in Directory.EnumerateFiles(CommonDesktop, "*.lnk"))
{
shortcuts.Add(Path.Join(CommonDesktop, shortcut));
}

return shortcuts;
}

/// <summary>
Expand All @@ -150,7 +163,7 @@ public static bool RemoveFromUnknownShortcuts(string shortcutPath)
/// Get the list of shortcuts whose deletion verdicts are unknown (as in, the user needs to be asked about deleting them when their operations finish)
/// </summary>
/// <returns>The list of shortcuts awaiting verdicts</returns>
public static List<string> GetAwaitingVerdicts()
public static List<string> GetUnknownShortcuts()
{
return UnknownShortcuts;
}
Expand All @@ -169,7 +182,7 @@ public static void TryRemoveNewShortcuts(IEnumerable<string> PreviousShortCutLis
switch (DesktopShortcutsDatabase.GetStatus(shortcut))
{
case Status.Delete:
DesktopShortcutsDatabase.DeleteShortcut(shortcut);
DesktopShortcutsDatabase.DeleteFromDisk(shortcut);
break;
case Status.Maintain:
Logger.Debug("Refraining from deleting new shortcut " + shortcut + ": user disabled its deletion");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ protected async Task MainThread()
break;
}

if (MainApp.Instance.OperationQueue.Count == 0 && DesktopShortcutsDatabase.GetAwaitingVerdicts().Count > 0)
if (MainApp.Instance.OperationQueue.Count == 0 && DesktopShortcutsDatabase.GetUnknownShortcuts().Any() && Settings.Get("AskToDeleteNewDesktopShortcuts"))
{
await DialogHelper.HandleNewDesktopShortcuts();
}
Expand Down
2 changes: 0 additions & 2 deletions src/UniGetUI/Controls/OperationWidgets/PackageOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,13 +370,11 @@ protected override async Task<AfterFinshAction> HandleSuccess()
new Dictionary<string, object?> { { "package", Package.Name } })
);


if (Settings.Get("AskToDeleteNewDesktopShortcuts"))
{
DesktopShortcutsDatabase.TryRemoveNewShortcuts(DesktopShortcutsBeforeStart);
}


return AfterFinshAction.TimeoutClose;
}

Expand Down
12 changes: 6 additions & 6 deletions src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<widgets:TranslatedTextBlock
Text="The shortcuts listed here will be either deleted or ignored if they're added after an update operation, depending on the value of the checkbox. Double-click them or click the button on their right for UniGetUI to ask you what to do next time they're detected."/>
Text="Here you can change UniGetUI's behaviour regarding the following shortcuts. Checking a shortcut will make UniGetUI delete it if if gets created on a future upgrade. Unchecking it will keep the shortcut intact"/>
<Button
Grid.Column="2"
HorizontalAlignment="Stretch"
Expand All @@ -39,7 +39,7 @@
</Grid.ColumnDefinitions>
<TextBlock
Grid.ColumnSpan="2"
Text="Do you really want to reset the deletable shortcuts list? This action cannot be reverted"
Text="Do you really want to reset this list? This action cannot be reverted."
Margin="0,0,0,0"
TextWrapping="WrapWholeWords"
/>
Expand Down Expand Up @@ -76,14 +76,14 @@
<DataTemplate x:DataType="local:ShortcutEntry">
<Grid ColumnSpacing="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox IsChecked="{x:Bind Enabled}" Checked="{x:Bind Enable}" Unchecked="{x:Bind Disable}" Grid.Column="0"/>
<widgets:LocalIcon Icon="localpc" Grid.Column="1" Height="24" Width="24"/>
<CheckBox IsChecked="{x:Bind IsChecked, Mode=TwoWay}" Grid.Column="0"/>
<widgets:LocalIcon Icon="Launch" Grid.Column="1" Height="24" Width="24"/>
<TextBlock Text="{x:Bind ShortcutPath}" Grid.Column="2" VerticalAlignment="Center"/>
<Button Click="{x:Bind OpenShortcutPath}" Height="32" Width="32" Padding="0" Grid.Column="3" IsEnabled="{x:Bind ShortcutExists}">
<widgets:LocalIcon Icon="launch" Height="24" Width="24"/>
Expand Down
88 changes: 61 additions & 27 deletions src/UniGetUI/Pages/DialogPages/DesktopShortcuts.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using UniGetUI.Core.Logging;
Expand All @@ -24,25 +26,45 @@ public sealed partial class DesktopShortcutsManager : Page
public event EventHandler? Close;
private ObservableCollection<ShortcutEntry> desktopShortcuts = new ObservableCollection<ShortcutEntry>();

public DesktopShortcutsManager()
private bool NewOnly = false;

public DesktopShortcutsManager(List<string>? NewShortcuts)
{
if (NewShortcuts is not null) NewOnly = true;


InitializeComponent();
DeletableDesktopShortcutsList.ItemsSource = desktopShortcuts;
DeletableDesktopShortcutsList.DoubleTapped += DeletableDesktopShortcutsList_DoubleTapped;
UpdateData(NewShortcuts);
}

public async Task UpdateData()
public void UpdateData(List<string>? NewShortcuts)
{
desktopShortcuts.Clear();

foreach (var (shortcutPath, shortcutEnabled) in DesktopShortcutsDatabase.GetDatabase())
if (NewShortcuts is not null) foreach (var path in NewShortcuts)
{
desktopShortcuts.Add(new(path, false));
}
else foreach (var (shortcutPath, shortcutEnabled) in DesktopShortcutsDatabase.GetDatabase())
{
var shortcutEntry = new ShortcutEntry(shortcutPath, shortcutEnabled, desktopShortcuts);
var shortcutEntry = new ShortcutEntry(shortcutPath, shortcutEnabled);
desktopShortcuts.Add(shortcutEntry);
}

foreach(var shortcut in desktopShortcuts)
{
shortcut.OnReset += (sender, path) =>
{
if (sender is not ShortcutEntry sh) throw new Exception();
DesktopShortcutsDatabase.ResetShortcut(sh.ShortcutPath);
desktopShortcuts.Remove(sh);
};
}
}

private async void DeletableDesktopShortcutsList_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
private void DeletableDesktopShortcutsList_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
if (DeletableDesktopShortcutsList.SelectedItem is ShortcutEntry shortcut)
{
Expand All @@ -56,7 +78,7 @@ private void CloseButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs
Close?.Invoke(this, EventArgs.Empty);
}

private async void YesResetButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
private void YesResetButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
foreach (ShortcutEntry shortcut in desktopShortcuts.ToArray())
{
Expand All @@ -70,38 +92,46 @@ private void NoResetButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArg
{
ConfirmResetFlyout.Hide();
}

public void SaveChangesAndClose()
{
Close?.Invoke(this, EventArgs.Empty);
foreach (var shortcut in desktopShortcuts)
{
DesktopShortcutsDatabase.AddToDatabase(shortcut.ShortcutPath, shortcut.IsChecked);
if (shortcut.IsChecked && File.Exists(shortcut.ShortcutPath))
{
DesktopShortcutsDatabase.DeleteFromDisk(shortcut.ShortcutPath);
}
DesktopShortcutsDatabase.RemoveFromUnknownShortcuts(shortcut.ShortcutPath);
}
}
}

public class ShortcutEntry
public class ShortcutEntry : INotifyPropertyChanged
{
public event EventHandler<EventArgs>? OnReset;

public string ShortcutPath { get; }
private bool _enabled;
public bool Enabled
public bool IsChecked
{
get
{
return _enabled;
}
get => _enabled;
set
{
_enabled = value;
DesktopShortcutsDatabase.Add(ShortcutPath, _enabled);
OnPropertyChanged();
}
}
public bool ShortcutExists
{
get
{
return File.Exists(ShortcutPath);
}
get => File.Exists(ShortcutPath);
}
private ObservableCollection<ShortcutEntry> List { get; }

public ShortcutEntry(string shortcutPath, bool enabled, ObservableCollection<ShortcutEntry> list)
public ShortcutEntry(string shortcutPath, bool enabled)
{
ShortcutPath = shortcutPath;
Enabled = enabled;
List = list;
IsChecked = enabled;
}

public void OpenShortcutPath()
Expand All @@ -111,18 +141,22 @@ public void OpenShortcutPath()

public void ResetConfiguration()
{
DesktopShortcutsDatabase.Reset(ShortcutPath);
List.Remove(this);
OnReset?.Invoke(this, EventArgs.Empty);
}

public void Enable()
public event PropertyChangedEventHandler? PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
Enabled = true;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void Disable()
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
Enabled = false;
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
}
Loading
Loading