Add login/logout button to plugin manger to sync subscriptions

This commit is contained in:
Stone_Red
2025-02-24 22:02:58 +01:00
parent 930da5d679
commit c74bc60209
8 changed files with 219 additions and 11 deletions
+42
View File
@@ -0,0 +1,42 @@
param(
[string]$AppPath,
[switch]$Enable,
[switch]$Disable
)
# Validate input
if ([string]::IsNullOrWhiteSpace($AppPath) -or !(Test-Path $AppPath)) {
exit 5 # Invalid app path
}
$AppName = [System.IO.Path]::GetFileNameWithoutExtension($AppPath)
$StartupPath = [Environment]::GetFolderPath('Startup')
$ShortcutPath = Join-Path $StartupPath "$AppName.lnk"
try {
if ($Enable) {
if (Test-Path $ShortcutPath) {
exit 2 # Already enabled
}
$WshShell = New-Object -ComObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath = $AppPath
$Shortcut.Save()
exit 0 # Success
}
elseif ($Disable) {
if (!(Test-Path $ShortcutPath)) {
exit 3 # Already disabled
}
Remove-Item $ShortcutPath -Force
exit 0 # Success
}
else {
exit 1 # Invalid parameters
}
}
catch {
exit 4 # Unexpected error
}
@@ -33,6 +33,9 @@ internal class PluginEntryDataContext(PluginMetadata pluginMetadata, ICommand co
public uint Id => pluginMetadata.Id;
public string? Path => path;
public bool IsLocalPlugin => string.IsNullOrWhiteSpace(pluginMetadata.ProfileUri?.ToString());
public ICommand Command => command;
public ButtonData InstallUninstallButtonData => new(mode == Mode.Install ? PackIconKind.Download : PackIconKind.Remove, GetInstallUninstallButtonText(), true, Command);
@@ -12,6 +12,7 @@ internal class PluginManagerDataContext : INotifyPropertyChanged
private string installedPluginsSearchText = string.Empty;
private bool isLoading = true;
private bool isSearching;
private bool isAuthenticated = false;
public ObservableCollection<PluginEntryDataContext> AllPlugins { get; } = [];
public ObservableCollection<PluginEntryDataContext> InstalledPlugins { get; } = [];
@@ -58,6 +59,19 @@ internal class PluginManagerDataContext : INotifyPropertyChanged
}
}
public bool IsAuthenticated
{
get => isAuthenticated;
set
{
isAuthenticated = value;
OnPropertyChanged();
OnPropertyChanged(nameof(LoginButtonText));
}
}
public string LoginButtonText => isAuthenticated ? (string)App.LanguageDictionary["logout"] : (string)App.LanguageDictionary["login"];
protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
+7 -1
View File
@@ -98,7 +98,13 @@
<Border Grid.Row="3" Grid.ColumnSpan="2" Padding="0 5 0 0" BorderThickness="0 2 0 0" BorderBrush="DarkGray">
<DockPanel>
<Image Source="{StaticResource ModioLogoBlueDark}" Cursor="Hand" Height="30" MouseUp="Image_MouseUp" HorizontalAlignment="Left" />
<Button HorizontalAlignment="Right" Click="CreatePluginButton_Click">
<Button DockPanel.Dock="Right" HorizontalAlignment="Right" Click="LogInButton_Click">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Login" Margin="0 0 10 0" />
<TextBlock Text="{Binding LoginButtonText}" />
</StackPanel>
</Button>
<Button DockPanel.Dock="Right" HorizontalAlignment="Right" Margin="0 0 10 0" Click="CreatePluginButton_Click">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Add" Margin="0 0 10 0" />
<TextBlock Text="{DynamicResource createNewPlugin}" />
+143 -10
View File
@@ -32,10 +32,9 @@ namespace DesktopMagic.Plugins;
/// </summary>
public partial class PluginManager : Window
{
private const int modIoGameId = 5665;
private readonly Client client = new Client(new Credentials("88e6ea774c3a502b06114e7fee0829ac"));
private const int ModIoGameId = 5665;
private const string ModIoApiKey = "88e6ea774c3a502b06114e7fee0829ac";
private readonly HttpClient httpClient = new();
private readonly PluginManagerDataContext pluginManagerDataContext = new();
private readonly string pluginsPath = Path.Combine(App.ApplicationDataPath, "Plugins");
private readonly string pluginDevelopmentPath = Path.Combine(App.ApplicationDataPath, "PluginDevelopment");
@@ -45,12 +44,26 @@ public partial class PluginManager : Window
Interval = TimeSpan.FromMilliseconds(300),
};
private Client modIoClient;
public PluginManager()
{
InitializeComponent();
Resources.MergedDictionaries.Add(App.LanguageDictionary);
string? modIoAccessToken = MainWindowDataContext.GetSettings().ModIoAccessToken;
if (modIoAccessToken is null)
{
modIoClient = new Client(new Credentials(ModIoApiKey));
}
else
{
modIoClient = new Client(new Credentials(ModIoApiKey, modIoAccessToken));
pluginManagerDataContext.IsAuthenticated = true;
}
DataContext = pluginManagerDataContext;
searchTimer.Tick += async (sender, e) =>
{
@@ -59,7 +72,7 @@ public partial class PluginManager : Window
};
}
public void Remove(string pluginPath, uint? id)
public async Task Remove(string pluginPath, uint id)
{
pluginManagerDataContext.IsLoading = true;
@@ -83,6 +96,11 @@ public partial class PluginManager : Window
_ = pluginManagerDataContext.InstalledPlugins.Remove(pluginEntryDataContext);
}
if (pluginManagerDataContext.IsAuthenticated)
{
await modIoClient.Games[ModIoGameId].Mods.Unsubscribe(id);
}
pluginManagerDataContext.IsLoading = false;
}
@@ -104,14 +122,14 @@ public partial class PluginManager : Window
if (pluginMetadata is not null)
{
pluginManagerDataContext.InstalledPlugins.Add(new PluginEntryDataContext(pluginMetadata, new CommandHandler(() => Remove(pluginPath, pluginMetadata.Id)), PluginEntryDataContext.Mode.Uninstall, pluginPath));
pluginManagerDataContext.InstalledPlugins.Add(new PluginEntryDataContext(pluginMetadata, new CommandHandler(async () => await Remove(pluginPath, pluginMetadata.Id)), PluginEntryDataContext.Mode.Uninstall, pluginPath));
_ = pluginIds.Add(pluginMetadata.Id);
}
}
Filter filter = ModFilter.Popular.Desc().Limit(100);
IAsyncEnumerable<Mod> mods = client.Games[modIoGameId].Mods.Search(filter).ToEnumerable();
IAsyncEnumerable<Mod> mods = modIoClient.Games[ModIoGameId].Mods.Search(filter).ToEnumerable();
await foreach (Mod mod in mods)
{
if (pluginIds.Contains(mod.Id))
@@ -122,6 +140,8 @@ public partial class PluginManager : Window
pluginManagerDataContext.AllPlugins.Add(new PluginEntryDataContext(new(mod), new CommandHandler(async () => await Install(mod)), PluginEntryDataContext.Mode.Install));
}
await SyncPlugins();
pluginManagerDataContext.IsLoading = false;
}
@@ -165,7 +185,7 @@ public partial class PluginManager : Window
if (!File.Exists(Path.Combine(pluginPath, "main.dll")))
{
Remove(pluginPath, mod.Id);
_ = Remove(pluginPath, mod.Id);
pluginManagerDataContext.IsLoading = false;
_ = MessageBox.Show("The plugin you are trying to install does not contain a \"main.dll\" file. Please contact the plugin author.", "Plugin Manager", MessageBoxButton.OK, MessageBoxImage.Error);
return;
@@ -178,7 +198,12 @@ public partial class PluginManager : Window
_ = pluginManagerDataContext.AllPlugins.Remove(pluginEntryDataContext);
}
pluginManagerDataContext.InstalledPlugins.Add(new PluginEntryDataContext(new PluginMetadata(mod), new CommandHandler(() => Remove(pluginPath, mod.Id)), PluginEntryDataContext.Mode.Uninstall));
if (pluginManagerDataContext.IsAuthenticated)
{
await modIoClient.Games[ModIoGameId].Mods.Subscribe(mod.Id);
}
pluginManagerDataContext.InstalledPlugins.Add(new PluginEntryDataContext(new PluginMetadata(mod), new CommandHandler(async () => await Remove(pluginPath, mod.Id)), PluginEntryDataContext.Mode.Uninstall, pluginPath));
pluginManagerDataContext.IsLoading = false;
}
@@ -230,7 +255,7 @@ public partial class PluginManager : Window
Filter filter = ModFilter.Name.Like($"{searchString}").And(ModFilter.Popular.Desc()).Limit(100);
IAsyncEnumerable<Mod> mods = client.Games[modIoGameId].Mods.Search(filter).ToEnumerable();
IAsyncEnumerable<Mod> mods = modIoClient.Games[ModIoGameId].Mods.Search(filter).ToEnumerable();
await foreach (Mod mod in mods)
{
if (pluginManagerDataContext.InstalledPlugins.Any(p => p.Id == mod.Id))
@@ -274,7 +299,7 @@ public partial class PluginManager : Window
Owner = this,
};
if (inputDialog.ShowDialog() is not true)
if (inputDialog.ShowDialog() != true)
{
return;
}
@@ -412,4 +437,112 @@ public class {pluginSafeName}Plugin : Plugin
_ = Process.Start(psi);
}
private async void LogInButton_Click(object sender, RoutedEventArgs e)
{
if (pluginManagerDataContext.IsAuthenticated)
{
MainWindowDataContext.GetSettings().ModIoAccessToken = null;
pluginManagerDataContext.IsAuthenticated = false;
return;
}
try
{
InputDialog inputDialog = new((string)FindResource("enterModIoEmail"), "Plugin Manager")
{
Owner = this,
};
if (inputDialog.ShowDialog() != true)
{
return;
}
await modIoClient.Auth.RequestCode(ModIoApiKey, inputDialog.ResponseText);
inputDialog = new((string)FindResource("enterModIoAccessToken"), "Plugin Manager")
{
Owner = this,
};
if (inputDialog.ShowDialog() != true)
{
return;
}
pluginManagerDataContext.IsLoading = true;
AccessToken accessToken = await modIoClient.Auth.SecurityCode(ModIoApiKey, inputDialog.ResponseText);
if (accessToken.Value is not null)
{
modIoClient = new Client(new Credentials(ModIoApiKey, accessToken.Value));
}
MainWindowDataContext.GetSettings().ModIoAccessToken = accessToken.Value;
pluginManagerDataContext.IsAuthenticated = true;
foreach (PluginEntryDataContext plugin in pluginManagerDataContext.InstalledPlugins)
{
if (!plugin.IsLocalPlugin)
{
try
{
await modIoClient.Games[ModIoGameId].Mods.Subscribe(plugin.Id);
}
catch (Exception ex)
{
App.Logger.LogError(ex.Message, source: "PluginManager");
}
}
}
await SyncPlugins();
}
catch (Exception ex)
{
App.Logger.LogError(ex.Message, source: "PluginManager");
_ = MessageBox.Show(ex.Message, "Plugin Manager", MessageBoxButton.OK, MessageBoxImage.Error);
}
pluginManagerDataContext.IsLoading = false;
}
private async Task SyncPlugins()
{
if (!pluginManagerDataContext.IsAuthenticated)
{
return;
}
IReadOnlyList<Mod> mods = await modIoClient.User.GetSubscriptions(ModFilter.GameId.Eq(ModIoGameId)).ToList();
List<PluginEntryDataContext> pluginsToRemove = [];
foreach (PluginEntryDataContext plugin in pluginManagerDataContext.InstalledPlugins)
{
if (!plugin.IsLocalPlugin && !mods.Any(m => m.Id == plugin.Id))
{
pluginsToRemove.Add(plugin);
}
}
foreach (PluginEntryDataContext plugin in pluginsToRemove)
{
if (plugin.Path is null)
{
continue;
}
await Remove(plugin.Path, plugin.Id);
}
IEnumerable<Mod> notInstalledMods = mods.Where(m => !pluginManagerDataContext.InstalledPlugins.Any(p => p.Id == m.Id));
foreach (Mod mod in notInstalledMods)
{
await Install(mod);
}
}
}
@@ -9,6 +9,10 @@
<system:String x:Key="unknown">Unbekannt</system:String>
<system:String x:Key="open">Öffnen</system:String>
<system:String x:Key="quit">Schließen</system:String>
<system:String x:Key="login">Einloggen</system:String>
<system:String x:Key="logout">Ausloggen</system:String>
<system:String x:Key="enterModIoEmail">Mod.io Account E-Mail eingeben</system:String>
<system:String x:Key="enterModIoAccessToken">Geben Sie Ihren mod.io Sicherheitscode ein</system:String>
<system:String x:Key="toggleEditMode">Bearbeitungsmodus umschalten</system:String>
<system:String x:Key="allPlugins">Alle Plugins</system:String>
<system:String x:Key="installedPlugins">Installierte Plugins</system:String>
@@ -9,6 +9,10 @@
<system:String x:Key="unknown">Unknown</system:String>
<system:String x:Key="open">Open</system:String>
<system:String x:Key="quit">Quit</system:String>
<system:String x:Key="login">Log In</system:String>
<system:String x:Key="logout">Log Out</system:String>
<system:String x:Key="enterModIoEmail">Enter your mod.io account E-mail</system:String>
<system:String x:Key="enterModIoAccessToken">Enter your mod.io security code</system:String>
<system:String x:Key="toggleEditMode">Toggle Edit Mode</system:String>
<system:String x:Key="allPlugins">All Plugins</system:String>
<system:String x:Key="installedPlugins">Installed Plugins</system:String>
@@ -37,6 +37,8 @@ internal class DesktopMagicSettings : INotifyPropertyChanged
}
}
public string? ModIoAccessToken { get; set; }
protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));