271 lines
10 KiB
C#
271 lines
10 KiB
C#
using System.Reflection;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using DynamicData;
|
|
using ModpackUpdater.Apps.Manager.Api;
|
|
using ModpackUpdater.Apps.Manager.Api.Model;
|
|
using ModpackUpdater.Apps.Manager.Api.Plugins.Features;
|
|
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
|
|
using ModpackUpdater.Apps.Manager.Settings;
|
|
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
|
|
using Pilz.Extensions;
|
|
using Pilz.Extensions.Collections;
|
|
using Pilz.Features;
|
|
using Pilz.UI.AvaloniaUI.Features;
|
|
using Pilz.UI.Symbols;
|
|
|
|
namespace ModpackUpdater.Apps.Manager.Ui;
|
|
|
|
public partial class MainWindow : Window, IMainApi
|
|
{
|
|
private WorkspaceFeature? curWs;
|
|
|
|
public MainWindowViewModel Model { get; } = new();
|
|
Window IMainApi.MainWindow => this;
|
|
public IMainApi MainApi => this;
|
|
public bool HasClosed { get; private set; }
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Title = $"{Title} (v{Assembly.GetExecutingAssembly().GetAppVersion().ToShortHumanString()})";
|
|
|
|
GridMain.DataContext = Model;
|
|
|
|
MenuItemWorkspace.Icon = AppGlobals.Symbols.GetImage(AppSymbols.workspace, SymbolSize.Small);
|
|
MenuItemWorkspacePreferences.Icon = AppGlobals.Symbols.GetImage(AppSymbols.settings, SymbolSize.Small);
|
|
MenuItemSaveWorkspace.Icon = AppGlobals.Symbols.GetImage(AppSymbols.save, SymbolSize.Small);
|
|
MenuItemNewWorkspace.Icon = AppGlobals.Symbols.GetImage(AppSymbols.new_window, SymbolSize.Small);
|
|
MenuItemRecentWorkspaces.Icon = AppGlobals.Symbols.GetImage(AppSymbols.time_machine, SymbolSize.Small);
|
|
MenuItemUpdate.Icon = AppGlobals.Symbols.GetImage(AppSymbols.update_done, SymbolSize.Small);
|
|
MenuItemTools.Icon = AppGlobals.Symbols.GetImage(AppSymbols.tools, SymbolSize.Small);
|
|
MenuItemCreateUpdate.Icon = AppGlobals.Symbols.GetImage(AppSymbols.add, SymbolSize.Small);
|
|
MenuItemRemoveUpdate.Icon = AppGlobals.Symbols.GetImage(AppSymbols.remove, SymbolSize.Small);
|
|
MenuItemAddAction.HeaderIcon = AppGlobals.Symbols.GetImage(AppSymbols.add, SymbolSize.Small);
|
|
MenuItemRemoveAction.HeaderIcon = AppGlobals.Symbols.GetImage(AppSymbols.remove, SymbolSize.Small);
|
|
ImageUpdate.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.update_done);
|
|
ImageMetadata.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.show_property);
|
|
ImageGeneral.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.normal_screen);
|
|
ImageSource.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.input);
|
|
ImageDestination.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.output);
|
|
|
|
PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).Ordered().InsertItemsTo(MenuItemNewWorkspace.Items,
|
|
customClickHandler: MenuItemNewWorkspaceItem_Click,
|
|
insertPrioSplitters: true);
|
|
|
|
PluginFeatureController.Instance.Features.Get(FeatureTypes.ActionsContextMenu).Ordered().InsertItemsTo(ContextMenuActions.Items,
|
|
customClickHandler: MenuItemActionItem_Click,
|
|
insertPrioSplitters: true);
|
|
|
|
PluginFeatureController.Instance.Functions.Get(FeatureTypes.Tools).InsertItemsTo(MenuItemTools.Items,
|
|
customClickHandler: MenuItemToolsItem_Click,
|
|
insertPrioSplitters: true);
|
|
}
|
|
|
|
private async Task LoadNewWorkspace(IWorkspace? workspace, WorkspaceFeature feature)
|
|
{
|
|
if (workspace is null)
|
|
return;
|
|
|
|
if (!await workspace.Load())
|
|
return;
|
|
|
|
if (workspace != Model.CurrentWorkspace)
|
|
{
|
|
Model.CurrentWorkspace = workspace;
|
|
curWs = feature;
|
|
}
|
|
|
|
AddToRecentFiles(workspace);
|
|
LoadRecentWorkspaces();
|
|
}
|
|
|
|
private async Task SaveWorkspace()
|
|
{
|
|
if (Model.CurrentWorkspace is not { } ws)
|
|
return;
|
|
|
|
Model.Progress.Start();
|
|
await ws.Save();
|
|
Model.Progress.Stop();
|
|
}
|
|
|
|
private void LoadRecentWorkspaces()
|
|
{
|
|
var settings = Program.Settings.Get<WorkspaceSettings>();
|
|
MenuItemRecentWorkspaces.Items.Clear();
|
|
|
|
settings.Workspaces.ForEach(config =>
|
|
{
|
|
if (PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).OfType<WorkspaceFeature>().FirstOrDefault(n => n.Identifier == config.ProviderId) is not WorkspaceFeature feature)
|
|
return;
|
|
|
|
var item = new MenuItem
|
|
{
|
|
Header = config.DisplayText,
|
|
Icon = feature.Icon,
|
|
DataContext = new MainWindowRecentFilesItem(config, feature),
|
|
};
|
|
item.Click += MenuItemRecentWorkspaceItem_Click;
|
|
MenuItemRecentWorkspaces.Items.Add(item);
|
|
});
|
|
}
|
|
|
|
private static void AddToRecentFiles(IWorkspace workspace)
|
|
{
|
|
var settings = Program.Settings.Get<WorkspaceSettings>();
|
|
settings.Workspaces.RemoveAll(n => n == workspace.Config);
|
|
settings.Workspaces.Insert(0, workspace.Config);
|
|
settings.Workspaces.Skip(20).ForEach(n => settings.Workspaces.Remove(n));
|
|
}
|
|
|
|
private async void Window_OnLoaded(object? sender, RoutedEventArgs e)
|
|
{
|
|
var updater = new AppUpdates("manager", this)
|
|
{
|
|
UsePopups = true,
|
|
};
|
|
updater.OnDownloadProgramUpdate += (_, _) => Model.Progress.Start();
|
|
await updater.UpdateApp();
|
|
Model.Progress.Stop();
|
|
|
|
LoadRecentWorkspaces();
|
|
}
|
|
|
|
private void Window_OnClosed(object? sender, EventArgs e)
|
|
{
|
|
HasClosed = true;
|
|
}
|
|
|
|
private async void Window_OnKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyModifiers == KeyModifiers.Control && e.Key == Key.Space)
|
|
await SaveWorkspace();
|
|
}
|
|
|
|
private async void MenuItemNewWorkspaceItem_Click(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is not MenuItem item || item.Tag is not WorkspaceFeature feature)
|
|
return;
|
|
|
|
var context = new WorkspaceContext(MainApi, null);
|
|
await feature.Configure(context);
|
|
if (!context.Canceled)
|
|
await LoadNewWorkspace(context.Workspace, feature);
|
|
}
|
|
|
|
private async void MenuItemWorkspacePreferences_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (curWs is null || Model.CurrentWorkspace is null)
|
|
return;
|
|
|
|
var context = new WorkspaceContext(MainApi, Model.CurrentWorkspace);
|
|
await curWs.Configure(context);
|
|
if (!context.Canceled)
|
|
await LoadNewWorkspace(context.Workspace, curWs);
|
|
}
|
|
|
|
private async void MenuItemSaveWorkspace_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
await SaveWorkspace();
|
|
}
|
|
|
|
private async void MenuItemRecentWorkspaceItem_Click(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is MenuItem item && item.DataContext is MainWindowRecentFilesItem tag && tag.Feature.CreateFromConfig(tag.Config) is IWorkspace workspace)
|
|
await LoadNewWorkspace(workspace, tag.Feature);
|
|
}
|
|
|
|
private async void MenuItemToolsItem_Click(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is MenuItem item && item.Tag is PluginFunction func)
|
|
await func.ExecuteAsync(new MainApiParameters(this));
|
|
}
|
|
|
|
private async void MenuItemActionItem_Click(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (sender is MenuItem item && item.Tag is PluginFunction func)
|
|
await func.ExecuteAsync(new MainApiParameters(this));
|
|
}
|
|
|
|
private void MenuItemCreateUpdate_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (Model.CurrentWorkspace?.UpdateInfos is null
|
|
|| Model.CurrentTreeNodes?.ElementAtOrDefault(1) is not { } nodeUpdates)
|
|
return;
|
|
|
|
var update = new UpdateInfo
|
|
{
|
|
Version = new(),
|
|
};
|
|
Model.CurrentWorkspace.UpdateInfos.Updates.Insert(0, update);
|
|
var item = new ActionSetTreeNode(update);
|
|
nodeUpdates.Nodes.Insert(0, item);
|
|
TreeViewWorkspace.SelectedItem = item;
|
|
TreeViewWorkspace.ScrollIntoView(item);
|
|
}
|
|
|
|
private void MenuItemRemoveUpdate_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (Model.CurrentWorkspace?.UpdateInfos is null
|
|
|| Model.CurrentTreeNodes?.ElementAtOrDefault(1) is not { } nodeUpdates
|
|
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|
|
|| nodeUpdate.Infos is not UpdateInfo update)
|
|
return;
|
|
|
|
nodeUpdates.Nodes.Remove(nodeUpdate);
|
|
Model.CurrentWorkspace.UpdateInfos.Updates.Remove(update);
|
|
}
|
|
|
|
private void ButtonAddAction_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (Model.CurrentWorkspace?.InstallInfos is not { } rootInfos
|
|
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|
|
|| Model.CurrentGridRows is not { } rows)
|
|
return;
|
|
|
|
InstallAction action;
|
|
|
|
switch (nodeUpdate.Infos)
|
|
{
|
|
case UpdateInfo updateInfos:
|
|
updateInfos.Actions.Add((UpdateAction)(action = new UpdateAction()));
|
|
break;
|
|
case InstallInfos installInfos:
|
|
installInfos.Actions.Add(action = new InstallAction());
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
var row = new MainWindowGridRow(action, rootInfos);
|
|
rows.List.Add(row);
|
|
DataGridActions.SelectedItem = row;
|
|
DataGridActions.ScrollIntoView(row, null);
|
|
}
|
|
|
|
private void ButtonRemoveAction_OnClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (Model.SelectedGridRow is not { } row
|
|
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|
|
|| Model.CurrentGridRows is not { } rows)
|
|
return;
|
|
|
|
switch (nodeUpdate.Infos)
|
|
{
|
|
case UpdateInfo updateInfos:
|
|
if (row.Action is UpdateAction action)
|
|
updateInfos.Actions.Remove(action);
|
|
break;
|
|
case InstallInfos installInfos:
|
|
installInfos.Actions.Remove(row.Action);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
rows.List.Remove(row);
|
|
}
|
|
} |