From 531a1c1e34237f1568320e2ccde98395512722b2 Mon Sep 17 00:00:00 2001 From: JFronny <33260128+jfronny@users.noreply.github.com> Date: Sat, 13 Feb 2021 14:36:12 +0100 Subject: [PATCH] Implement app controls and filters in UpToolEto --- UpTool2/MainForm.cs | 7 +- UpToolCLI/CacheManagement.cs | 6 +- UpToolCLI/PackageManagement.cs | 10 +-- .../UpToolEto/Controls/AppControlButton.cs | 65 +++++++++++++++++++ UpToolEto/UpToolEto/Controls/AppControls.cs | 48 ++++++++++++++ UpToolEto/UpToolEto/Controls/AppList.cs | 40 ++++++++---- .../Controls/AppListSearchProvider.cs | 32 +++++++++ UpToolEto/UpToolEto/Controls/AppPanel.cs | 33 +++++++--- UpToolEto/UpToolEto/Forms/MainForm.cs | 18 ++--- UpToolEto/UpToolEto/Main.cs | 43 ++++++------ UpToolLib/DataStructures/Status.cs | 7 +- UpToolLib/v1/Tool/AppExtras.cs | 2 + 12 files changed, 248 insertions(+), 63 deletions(-) create mode 100644 UpToolEto/UpToolEto/Controls/AppControlButton.cs create mode 100644 UpToolEto/UpToolEto/Controls/AppControls.cs create mode 100644 UpToolEto/UpToolEto/Controls/AppListSearchProvider.cs diff --git a/UpTool2/MainForm.cs b/UpTool2/MainForm.cs index 6cf726d..75a80e4 100644 --- a/UpTool2/MainForm.cs +++ b/UpTool2/MainForm.cs @@ -139,7 +139,7 @@ namespace UpTool2 args.Graphics.DrawImage(sidebarIcon.BackgroundImage, args.ClipRectangle, new Rectangle(new Point(0, 0), sidebarIcon.BackgroundImage.Size), GraphicsUnit.Pixel); }; - bool updateable = !app.Local && (app.Status & Status.Updatable) == Status.Updatable; + bool updateable = !app.Local && app.Status.Contains(Status.Updatable); sidebarIcon.Click += (sender, e) => { infoPanel_Title.Text = app.Name; @@ -164,7 +164,7 @@ namespace UpTool2 else action_update.ResetBackColor(); action_run.Tag = app; - action_run.Enabled = (app.Status & Status.Installed) == Status.Installed && !app.Local && + action_run.Enabled = app.Status.Contains(Status.Installed) && !app.Local && app.Runnable && Directory.Exists(app.AppPath); }; if (updateable) @@ -248,8 +248,7 @@ namespace UpTool2 { Panel sidebarIcon = (Panel) sidebarPanel.Controls[i]; App app = (App) sidebarIcon.Tag; - sidebarIcon.Visible = apps.Contains(app) && - ((int) app.Status & (int) (Program.Online ? status : Status.Installed)) != 0; + sidebarIcon.Visible = apps.Contains(app) && app.Status.Contains(Program.Online ? status : Status.Installed); } ClearSelection(); } diff --git a/UpToolCLI/CacheManagement.cs b/UpToolCLI/CacheManagement.cs index 979715a..7c85397 100644 --- a/UpToolCLI/CacheManagement.cs +++ b/UpToolCLI/CacheManagement.cs @@ -43,14 +43,14 @@ namespace UpToolCLI private static void List() { Program.Lib.V2.RepoManagement.GetReposFromDisk(); - Console.WriteLine(Program.Lib.V1.Apps.Where(s => (s.Value.Status & Status.Installed) == Status.Installed) + Console.WriteLine(Program.Lib.V1.Apps.Where(s => s.Value.Status.Contains(Status.Installed)) .ToStringTable(new[] { "Name", "State", "Guid" }, u => u.Value.Name, u => u.Value.Local ? "Local" : - (u.Value.Status & Status.Updatable) == Status.Updatable ? "Updatable" : "None", + u.Value.Status.Contains(Status.Updatable) ? "Updatable" : "None", u => u.Key)); } @@ -85,7 +85,7 @@ namespace UpToolCLI Program.Lib.V2.RepoManagement.GetReposFromDisk(); Console.WriteLine(); IEnumerable tmp = Program.Lib.V1.Apps.Where(s => - (s.Value.Status & Status.Updatable) == Status.Updatable).Select(s => s.Value); + s.Value.Status.Contains(Status.Updatable)).Select(s => s.Value); IEnumerable apps = tmp as App[] ?? tmp.ToArray(); int updatableCount = apps.Count(); Console.WriteLine(updatableCount == 0 diff --git a/UpToolCLI/PackageManagement.cs b/UpToolCLI/PackageManagement.cs index bff796a..c56046f 100644 --- a/UpToolCLI/PackageManagement.cs +++ b/UpToolCLI/PackageManagement.cs @@ -86,7 +86,7 @@ namespace UpToolCLI else { App tmp = apps.First(); - if ((tmp.Status & Status.Installed) == Status.Installed) + if (tmp.Status.Contains(Status.Installed)) Console.WriteLine("Package is already installed"); else { @@ -106,7 +106,7 @@ namespace UpToolCLI else { App tmp = apps.First(); - if ((tmp.Status & Status.Updatable) == Status.Updatable) + if (tmp.Status.Contains(Status.Updatable)) { Console.WriteLine($"Upgrading {tmp.Name}"); Program.Lib.V1.AppExtras.Update(tmp, force); @@ -141,7 +141,7 @@ namespace UpToolCLI else { App tmp = apps.First(); - if ((tmp.Status & Status.Installed) == Status.Installed) + if (tmp.Status.Contains(Status.Installed)) { Console.WriteLine($"Removing {tmp.Name}"); Program.Lib.V1.AppExtras.Remove(tmp, false); @@ -161,7 +161,7 @@ namespace UpToolCLI else { App tmp = apps.First(); - if ((tmp.Status & Status.Installed) == Status.Installed) + if (tmp.Status.Contains(Status.Installed)) { Console.WriteLine($"Purging {tmp.Name}"); Program.Lib.V1.AppExtras.Remove(tmp, true); @@ -176,7 +176,7 @@ namespace UpToolCLI { Program.Lib.V2.RepoManagement.GetReposFromDisk(); foreach (KeyValuePair app in Program.Lib.V1.Apps.Where(s => - (s.Value.Status & Status.Updatable) == Status.Updatable)) + s.Value.Status.Contains(Status.Updatable))) { Console.WriteLine($"Updating {app.Value.Name}"); Program.Lib.V1.AppExtras.Update(app.Value, false); diff --git a/UpToolEto/UpToolEto/Controls/AppControlButton.cs b/UpToolEto/UpToolEto/Controls/AppControlButton.cs new file mode 100644 index 0000000..5d8bc9a --- /dev/null +++ b/UpToolEto/UpToolEto/Controls/AppControlButton.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Eto.Drawing; +using Eto.Forms; +using UpToolLib.v2; +using UpToolLib.v2.TaskQueue; + +namespace UpToolEto.Controls +{ + public abstract class AppControlButton : Button + { + public abstract void ReloadState(); + public abstract void SetApp(App app); + public abstract void Clear(); + } + + public class AppControlButton : AppControlButton where T : KnownAppTask + { + private readonly IList _tasks; + private readonly Func _enabledCheck; + private readonly Color _defaultColor; + private App _app; + + public AppControlButton(string text, Func factory, IList tasks, Action reloadState, Func enabledCheck) + { + _tasks = tasks; + _enabledCheck = enabledCheck; + _defaultColor = BackgroundColor; + Text = text; + Click += (_, _) => + { + bool found = false; + for (var i = tasks.ToArray().Length - 1; i >= 0; i--) + { + if (tasks[i] is T t && t.App == _app) + { + found = true; + tasks.RemoveAt(i); + } + } + if (!found) + tasks.Add(factory(_app, ReloadState)); + reloadState(); + }; + } + + public override void ReloadState() + { + Enabled = _enabledCheck(_app); + BackgroundColor = _tasks.Any(s => s is T t && t.App == _app) ? Colors.Green : _defaultColor; + } + + public override void SetApp(App app) + { + _app = app; + ReloadState(); + } + + public override void Clear() + { + Enabled = false; + } + } +} \ No newline at end of file diff --git a/UpToolEto/UpToolEto/Controls/AppControls.cs b/UpToolEto/UpToolEto/Controls/AppControls.cs new file mode 100644 index 0000000..a45629c --- /dev/null +++ b/UpToolEto/UpToolEto/Controls/AppControls.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using Eto.Drawing; +using Eto.Forms; +using UpToolLib.DataStructures; +using UpToolLib.v2; +using UpToolLib.v2.TaskQueue; + +namespace UpToolEto.Controls +{ + public class AppControls : StackLayout + { + private readonly List _buttons; + public AppControls(TaskFactory factory, IList tasks) + { + _buttons = new List + { + new AppControlButton("Install", factory.CreateInstall, tasks, ReloadState, + app => !app.Status.Contains(Status.Installed)), + new AppControlButton("Update", factory.CreateUpdate, tasks, ReloadState, + app => app.Status.Contains(Status.Updatable)), + new AppControlButton("Remove", factory.CreateRemove, tasks, ReloadState, + app => app.Status.Contains(Status.Installed)) + }; + foreach (AppControlButton button in _buttons) Items.Add(button); + if (Main.DebugColors) + BackgroundColor = Colors.Yellow; + Orientation = Orientation.Horizontal; + } + + public void SetApp(App app) + { + Visible = true; + foreach (AppControlButton button in _buttons) button.SetApp(app); + ReloadState(); + } + + public void Clear() + { + Visible = false; + foreach (AppControlButton button in _buttons) button.Clear(); + } + + private void ReloadState() + { + foreach (AppControlButton button in _buttons) button.ReloadState(); + } + } +} diff --git a/UpToolEto/UpToolEto/Controls/AppList.cs b/UpToolEto/UpToolEto/Controls/AppList.cs index 28c2c06..15863d6 100644 --- a/UpToolEto/UpToolEto/Controls/AppList.cs +++ b/UpToolEto/UpToolEto/Controls/AppList.cs @@ -2,42 +2,54 @@ using System; using System.Collections.Generic; using Eto.Drawing; using Eto.Forms; +using UpToolLib.v1.Tool; using UpToolLib.v2; namespace UpToolEto.Controls { - public class AppList : Scrollable + public class AppList : StackLayout { - private readonly IDictionary _apps; + private readonly AppExtras _extras; private readonly Action _itemClickEvent; private readonly StackLayout _layout; + private readonly AppListSearchProvider _searchProvider; - public AppList(IDictionary apps, Action itemClickEvent) + public AppList(AppExtras extras, Action itemClickEvent, bool online) { - _apps = apps; + _extras = extras; _itemClickEvent = itemClickEvent; + _searchProvider = new AppListSearchProvider(online, Update); + Items.Add(_searchProvider); _layout = new StackLayout { Padding = 10, Orientation = Orientation.Vertical, Width = 200 }; - Content = _layout; + Scrollable scrollable = new() + { + Content = _layout + }; + if (Main.DebugColors) + scrollable.BackgroundColor = Colors.YellowGreen; + Items.Add(new StackLayoutItem(scrollable, VerticalAlignment.Stretch, true)); + Orientation = Orientation.Vertical; + if (Main.DebugColors) + BackgroundColor = Colors.Green; Update(); } public void Update() { _layout.Items.Clear(); - foreach ((Guid id, App app) in _apps) - { - _layout.Items.Add(new Button((_, _) => _itemClickEvent(id, app)) - { - Text = app.Name, - Image = (Icon)app.Icon, - ImagePosition = ButtonImagePosition.Left, - }); - } + foreach (App app in _extras.FindApps(_searchProvider.GetSearchTerms())) + if (_searchProvider.Matches(app)) + _layout.Items.Add(new Button((_, _) => _itemClickEvent(app.Id, app)) + { + Text = app.Name, + Image = (Icon)app.Icon, + ImagePosition = ButtonImagePosition.Left, + }); } } } diff --git a/UpToolEto/UpToolEto/Controls/AppListSearchProvider.cs b/UpToolEto/UpToolEto/Controls/AppListSearchProvider.cs new file mode 100644 index 0000000..b164f95 --- /dev/null +++ b/UpToolEto/UpToolEto/Controls/AppListSearchProvider.cs @@ -0,0 +1,32 @@ +using System; +using Eto.Forms; +using UpToolLib.DataStructures; +using UpToolLib.v2; + +//TODO implement +namespace UpToolEto.Controls +{ + public class AppListSearchProvider : StackLayout + { + private readonly bool _online; + private readonly TextBox _search; + private readonly EnumDropDown _state; + public AppListSearchProvider(bool online, Action refresh) + { + _online = online; + _search = new SearchBox(); + _state = new EnumDropDown(); + _state.SelectedValue = online ? Status.NotInstalled : Status.Installed; + _state.Enabled = online; + _search.TextChanged += (_, _) => refresh(); + _state.SelectedIndexChanged += (_, _) => refresh(); + Orientation = Orientation.Vertical; + Items.Add(new StackLayoutItem(_search, HorizontalAlignment.Stretch)); + Items.Add(_state); + } + + public bool Matches(App app) => app.Status.Contains(_online ? _state.SelectedValue : Status.Installed); + + public string GetSearchTerms() => _search.Text; + } +} \ No newline at end of file diff --git a/UpToolEto/UpToolEto/Controls/AppPanel.cs b/UpToolEto/UpToolEto/Controls/AppPanel.cs index 51cfd1b..51082e5 100644 --- a/UpToolEto/UpToolEto/Controls/AppPanel.cs +++ b/UpToolEto/UpToolEto/Controls/AppPanel.cs @@ -1,38 +1,55 @@ +using System.Collections.Generic; using Eto.Drawing; using Eto.Forms; +using UpToolLib.DataStructures; +using UpToolLib.v1.Tool; using UpToolLib.v2; +using UpToolLib.v2.TaskQueue; namespace UpToolEto.Controls { public class AppPanel : Panel { - private readonly Label _appNameLabel; + private readonly Button _appNameLabel; private readonly Label _appDescriptionLabel; - public AppPanel() + private readonly AppControls _appControls; + private App _app; + public AppPanel(TaskFactory factory, AppExtras extras, IList tasks) { _appDescriptionLabel = new Label(); - _appNameLabel = new Label(); + _appNameLabel = new Button((_, _) => extras.RunApp(_app)); _appNameLabel.Font = new Font(_appNameLabel.Font.Family, _appNameLabel.Font.Size * 2); + _appControls = new AppControls(factory, tasks); Content = new StackLayout { Items = { - _appNameLabel, - _appDescriptionLabel - } + new StackLayoutItem(_appNameLabel, HorizontalAlignment.Center), + new StackLayoutItem(_appDescriptionLabel, HorizontalAlignment.Center, true), + new StackLayoutItem(_appControls, HorizontalAlignment.Stretch) + }, + Orientation = Orientation.Vertical }; + if (Main.DebugColors) + BackgroundColor = Colors.Red; + Clear(); } - public void FromApp(App app) + public void SetApp(App app) { + _app = app; _appNameLabel.Text = app.Name; + _appNameLabel.Enabled = app.Status.Contains(Status.Installed) && app.Runnable; _appDescriptionLabel.Text = app.Description; + _appControls.SetApp(app); } public void Clear() { _appNameLabel.Text = "Welcome to UpTool2"; + _appNameLabel.Enabled = false; _appDescriptionLabel.Text = "Select an app to get started"; + _appControls.Clear(); } } -} \ No newline at end of file +} diff --git a/UpToolEto/UpToolEto/Forms/MainForm.cs b/UpToolEto/UpToolEto/Forms/MainForm.cs index 283450f..93745ff 100644 --- a/UpToolEto/UpToolEto/Forms/MainForm.cs +++ b/UpToolEto/UpToolEto/Forms/MainForm.cs @@ -1,32 +1,34 @@ +using System.Collections.Generic; using Eto.Drawing; using Eto.Forms; using UpToolEto.Controls; using UpToolLib; using UpToolLib.DataStructures; +using UpToolLib.v2.TaskQueue; -//TODO implement tasks queue UI -//TODO keep track of app state -//TODO app filters (search by name/tags) -//TODO add control_upload action_run action_update action_remove action_install +//TODO implement tasks queue UI and add control to execute queue, also needs to clear AppPanel and reload AppList +//TODO add control_upload namespace UpToolEto.Forms { public partial class MainForm : Form { private readonly AppPanel _appPanel; + private readonly IList _tasks; public MainForm(InitScreen init, UpToolLibMain lib, IExternalFunctionality platform, bool online) { + _tasks = new List(); Title = "UpTool2"; MinimumSize = new Size(600, 100); - AppList appList = new(lib.V1.Apps, (guid, app) => _appPanel.FromApp(app)); - _appPanel = new AppPanel(); + AppList appList = new(lib.V1.AppExtras, (_, app) => _appPanel.SetApp(app), online); + _appPanel = new AppPanel(lib.V2.TaskFactory, lib.V1.AppExtras, _tasks); Content = new StackLayout { Padding = 10, Items = { - appList, - new StackLayoutItem(_appPanel, true) + new StackLayoutItem(appList, VerticalAlignment.Stretch), + new StackLayoutItem(_appPanel, VerticalAlignment.Stretch, true) }, Orientation = Orientation.Horizontal }; diff --git a/UpToolEto/UpToolEto/Main.cs b/UpToolEto/UpToolEto/Main.cs index a481660..49e9439 100644 --- a/UpToolEto/UpToolEto/Main.cs +++ b/UpToolEto/UpToolEto/Main.cs @@ -20,17 +20,17 @@ namespace UpToolEto public class Main { private readonly IExternalFunctionality _platform; - private readonly UpToolLibMain _lib; private readonly Application _application; private readonly Action _activityExistsException; private readonly InitScreen _init; private readonly bool _skipFetch; + public static bool DebugColors { get; private set; } public Main(Application application, Action activityExistsException, string[] args) { _skipFetch = args.Contains("--skip-fetch"); + DebugColors = args.Contains("--debug-colors"); _platform = new UTLibFunctions(application); - _lib = new UpToolLibMain(_platform); _application = application; _activityExistsException = activityExistsException; _init = new(application, _platform); @@ -44,40 +44,41 @@ namespace UpToolEto private void InitThread() { + UpToolLibMain lib = null; try { + lib = new UpToolLibMain(_platform); _init.SetText("Initializing paths"); - if (!Directory.Exists(_lib.V1.PathTool.Dir)) - Directory.CreateDirectory(_lib.V1.PathTool.Dir); - FixXml(_lib.V1.XmlTool, _lib.V1.PathTool); + if (!Directory.Exists(lib.V1.PathTool.Dir)) + Directory.CreateDirectory(lib.V1.PathTool.Dir); + FixXml(lib.V1.XmlTool, lib.V1.PathTool); _init.SetText("Performing checks"); bool online = false; UpdateCheck updateCheck = null; try { - updateCheck = _lib.V2.UpdateChecker.Check(); + updateCheck = lib.V2.UpdateChecker.Check(); online = true; } catch { _platform.Log("Could not perform update check, starting offline"); } - if (online && UpdateCheck(updateCheck, _lib.V1.PathTool, _init)) - { + if (online && UpdateCheck(updateCheck, lib.V1.PathTool, _init)) _platform.Log("Quitting"); - _application.Quit(); - return; - } - if (!Directory.Exists(_lib.V1.PathTool.GetRelative("Apps"))) - Directory.CreateDirectory(_lib.V1.PathTool.GetRelative("Apps")); - if (!_skipFetch && online) + else { - _init.SetText("Fetching repos"); - _lib.V2.RepoManagement.FetchRepos(); + if (!Directory.Exists(lib.V1.PathTool.GetRelative("Apps"))) + Directory.CreateDirectory(lib.V1.PathTool.GetRelative("Apps")); + if (!_skipFetch && online) + { + _init.SetText("Fetching repos"); + lib.V2.RepoManagement.FetchRepos(); + } + lib.V2.RepoManagement.GetReposFromDisk(); + _init.SetText("Opening"); + _application.Invoke(() => _application.Run(new MainForm(_init, lib, _platform, online))); } - _lib.V2.RepoManagement.GetReposFromDisk(); - _init.SetText("Opening"); - _application.Invoke(() => _application.Run(new MainForm(_init, _lib, _platform, online))); } catch (MutexLockLockedException) { @@ -90,11 +91,13 @@ namespace UpToolEto } catch (Exception e) { + lib?.Dispose(); _platform.Log(e.ToString()); } finally { - _lib?.Dispose(); + lib?.Dispose(); + _application.Invoke(() => _application.Quit()); } } diff --git a/UpToolLib/DataStructures/Status.cs b/UpToolLib/DataStructures/Status.cs index d1ed9b9..aa8502a 100644 --- a/UpToolLib/DataStructures/Status.cs +++ b/UpToolLib/DataStructures/Status.cs @@ -9,6 +9,11 @@ namespace UpToolLib.DataStructures Updatable = 2, Installed = 4, Local = 8, - All = 15 + All = 0 + } + + public static class StatusExtensions + { + public static bool Contains(this Status status, Status other) => (status & other) == other; } } \ No newline at end of file diff --git a/UpToolLib/v1/Tool/AppExtras.cs b/UpToolLib/v1/Tool/AppExtras.cs index b6a124a..ecdca84 100644 --- a/UpToolLib/v1/Tool/AppExtras.cs +++ b/UpToolLib/v1/Tool/AppExtras.cs @@ -108,6 +108,8 @@ namespace UpToolLib.v1.Tool public App[] FindApps(string identifier) { + if (string.IsNullOrWhiteSpace(identifier)) + return _apps.Values.ToArray(); IEnumerable> tmp1 = _apps.Where(s => s.Key.ToString().StartsWith(identifier)); tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Name.Contains(identifier))); tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Description.Contains(identifier)));