Implement app controls and filters in UpToolEto

This commit is contained in:
JFronny 2021-02-13 14:36:12 +01:00
parent 5814336814
commit 531a1c1e34
12 changed files with 248 additions and 63 deletions

View File

@ -139,7 +139,7 @@ namespace UpTool2
args.Graphics.DrawImage(sidebarIcon.BackgroundImage, args.ClipRectangle, args.Graphics.DrawImage(sidebarIcon.BackgroundImage, args.ClipRectangle,
new Rectangle(new Point(0, 0), sidebarIcon.BackgroundImage.Size), GraphicsUnit.Pixel); 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) => sidebarIcon.Click += (sender, e) =>
{ {
infoPanel_Title.Text = app.Name; infoPanel_Title.Text = app.Name;
@ -164,7 +164,7 @@ namespace UpTool2
else else
action_update.ResetBackColor(); action_update.ResetBackColor();
action_run.Tag = app; 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); app.Runnable && Directory.Exists(app.AppPath);
}; };
if (updateable) if (updateable)
@ -248,8 +248,7 @@ namespace UpTool2
{ {
Panel sidebarIcon = (Panel) sidebarPanel.Controls[i]; Panel sidebarIcon = (Panel) sidebarPanel.Controls[i];
App app = (App) sidebarIcon.Tag; App app = (App) sidebarIcon.Tag;
sidebarIcon.Visible = apps.Contains(app) && sidebarIcon.Visible = apps.Contains(app) && app.Status.Contains(Program.Online ? status : Status.Installed);
((int) app.Status & (int) (Program.Online ? status : Status.Installed)) != 0;
} }
ClearSelection(); ClearSelection();
} }

View File

@ -43,14 +43,14 @@ namespace UpToolCLI
private static void List() private static void List()
{ {
Program.Lib.V2.RepoManagement.GetReposFromDisk(); 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[] .ToStringTable(new[]
{ {
"Name", "State", "Guid" "Name", "State", "Guid"
}, },
u => u.Value.Name, u => u.Value.Name,
u => u.Value.Local ? "Local" : 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)); u => u.Key));
} }
@ -85,7 +85,7 @@ namespace UpToolCLI
Program.Lib.V2.RepoManagement.GetReposFromDisk(); Program.Lib.V2.RepoManagement.GetReposFromDisk();
Console.WriteLine(); Console.WriteLine();
IEnumerable<App> tmp = Program.Lib.V1.Apps.Where(s => IEnumerable<App> 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<App> apps = tmp as App[] ?? tmp.ToArray(); IEnumerable<App> apps = tmp as App[] ?? tmp.ToArray();
int updatableCount = apps.Count(); int updatableCount = apps.Count();
Console.WriteLine(updatableCount == 0 Console.WriteLine(updatableCount == 0

View File

@ -86,7 +86,7 @@ namespace UpToolCLI
else else
{ {
App tmp = apps.First(); App tmp = apps.First();
if ((tmp.Status & Status.Installed) == Status.Installed) if (tmp.Status.Contains(Status.Installed))
Console.WriteLine("Package is already installed"); Console.WriteLine("Package is already installed");
else else
{ {
@ -106,7 +106,7 @@ namespace UpToolCLI
else else
{ {
App tmp = apps.First(); App tmp = apps.First();
if ((tmp.Status & Status.Updatable) == Status.Updatable) if (tmp.Status.Contains(Status.Updatable))
{ {
Console.WriteLine($"Upgrading {tmp.Name}"); Console.WriteLine($"Upgrading {tmp.Name}");
Program.Lib.V1.AppExtras.Update(tmp, force); Program.Lib.V1.AppExtras.Update(tmp, force);
@ -141,7 +141,7 @@ namespace UpToolCLI
else else
{ {
App tmp = apps.First(); App tmp = apps.First();
if ((tmp.Status & Status.Installed) == Status.Installed) if (tmp.Status.Contains(Status.Installed))
{ {
Console.WriteLine($"Removing {tmp.Name}"); Console.WriteLine($"Removing {tmp.Name}");
Program.Lib.V1.AppExtras.Remove(tmp, false); Program.Lib.V1.AppExtras.Remove(tmp, false);
@ -161,7 +161,7 @@ namespace UpToolCLI
else else
{ {
App tmp = apps.First(); App tmp = apps.First();
if ((tmp.Status & Status.Installed) == Status.Installed) if (tmp.Status.Contains(Status.Installed))
{ {
Console.WriteLine($"Purging {tmp.Name}"); Console.WriteLine($"Purging {tmp.Name}");
Program.Lib.V1.AppExtras.Remove(tmp, true); Program.Lib.V1.AppExtras.Remove(tmp, true);
@ -176,7 +176,7 @@ namespace UpToolCLI
{ {
Program.Lib.V2.RepoManagement.GetReposFromDisk(); Program.Lib.V2.RepoManagement.GetReposFromDisk();
foreach (KeyValuePair<Guid, App> app in Program.Lib.V1.Apps.Where(s => foreach (KeyValuePair<Guid, App> 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}"); Console.WriteLine($"Updating {app.Value.Name}");
Program.Lib.V1.AppExtras.Update(app.Value, false); Program.Lib.V1.AppExtras.Update(app.Value, false);

View File

@ -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<T> : AppControlButton where T : KnownAppTask
{
private readonly IList<AppTask> _tasks;
private readonly Func<App, bool> _enabledCheck;
private readonly Color _defaultColor;
private App _app;
public AppControlButton(string text, Func<App, Action?, AppTask> factory, IList<AppTask> tasks, Action reloadState, Func<App, bool> 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;
}
}
}

View File

@ -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<AppControlButton> _buttons;
public AppControls(TaskFactory factory, IList<AppTask> tasks)
{
_buttons = new List<AppControlButton>
{
new AppControlButton<InstallTask>("Install", factory.CreateInstall, tasks, ReloadState,
app => !app.Status.Contains(Status.Installed)),
new AppControlButton<UpdateTask>("Update", factory.CreateUpdate, tasks, ReloadState,
app => app.Status.Contains(Status.Updatable)),
new AppControlButton<RemoveTask>("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();
}
}
}

View File

@ -2,42 +2,54 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Eto.Drawing; using Eto.Drawing;
using Eto.Forms; using Eto.Forms;
using UpToolLib.v1.Tool;
using UpToolLib.v2; using UpToolLib.v2;
namespace UpToolEto.Controls namespace UpToolEto.Controls
{ {
public class AppList : Scrollable public class AppList : StackLayout
{ {
private readonly IDictionary<Guid, App> _apps; private readonly AppExtras _extras;
private readonly Action<Guid, App> _itemClickEvent; private readonly Action<Guid, App> _itemClickEvent;
private readonly StackLayout _layout; private readonly StackLayout _layout;
private readonly AppListSearchProvider _searchProvider;
public AppList(IDictionary<Guid, App> apps, Action<Guid, App> itemClickEvent) public AppList(AppExtras extras, Action<Guid, App> itemClickEvent, bool online)
{ {
_apps = apps; _extras = extras;
_itemClickEvent = itemClickEvent; _itemClickEvent = itemClickEvent;
_searchProvider = new AppListSearchProvider(online, Update);
Items.Add(_searchProvider);
_layout = new StackLayout _layout = new StackLayout
{ {
Padding = 10, Padding = 10,
Orientation = Orientation.Vertical, Orientation = Orientation.Vertical,
Width = 200 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(); Update();
} }
public void Update() public void Update()
{ {
_layout.Items.Clear(); _layout.Items.Clear();
foreach ((Guid id, App app) in _apps) foreach (App app in _extras.FindApps(_searchProvider.GetSearchTerms()))
{ if (_searchProvider.Matches(app))
_layout.Items.Add(new Button((_, _) => _itemClickEvent(id, app)) _layout.Items.Add(new Button((_, _) => _itemClickEvent(app.Id, app))
{ {
Text = app.Name, Text = app.Name,
Image = (Icon)app.Icon, Image = (Icon)app.Icon,
ImagePosition = ButtonImagePosition.Left, ImagePosition = ButtonImagePosition.Left,
}); });
}
} }
} }
} }

View File

@ -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<Status> _state;
public AppListSearchProvider(bool online, Action refresh)
{
_online = online;
_search = new SearchBox();
_state = new EnumDropDown<Status>();
_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;
}
}

View File

@ -1,38 +1,55 @@
using System.Collections.Generic;
using Eto.Drawing; using Eto.Drawing;
using Eto.Forms; using Eto.Forms;
using UpToolLib.DataStructures;
using UpToolLib.v1.Tool;
using UpToolLib.v2; using UpToolLib.v2;
using UpToolLib.v2.TaskQueue;
namespace UpToolEto.Controls namespace UpToolEto.Controls
{ {
public class AppPanel : Panel public class AppPanel : Panel
{ {
private readonly Label _appNameLabel; private readonly Button _appNameLabel;
private readonly Label _appDescriptionLabel; private readonly Label _appDescriptionLabel;
public AppPanel() private readonly AppControls _appControls;
private App _app;
public AppPanel(TaskFactory factory, AppExtras extras, IList<AppTask> tasks)
{ {
_appDescriptionLabel = new Label(); _appDescriptionLabel = new Label();
_appNameLabel = new Label(); _appNameLabel = new Button((_, _) => extras.RunApp(_app));
_appNameLabel.Font = new Font(_appNameLabel.Font.Family, _appNameLabel.Font.Size * 2); _appNameLabel.Font = new Font(_appNameLabel.Font.Family, _appNameLabel.Font.Size * 2);
_appControls = new AppControls(factory, tasks);
Content = new StackLayout Content = new StackLayout
{ {
Items = Items =
{ {
_appNameLabel, new StackLayoutItem(_appNameLabel, HorizontalAlignment.Center),
_appDescriptionLabel 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.Text = app.Name;
_appNameLabel.Enabled = app.Status.Contains(Status.Installed) && app.Runnable;
_appDescriptionLabel.Text = app.Description; _appDescriptionLabel.Text = app.Description;
_appControls.SetApp(app);
} }
public void Clear() public void Clear()
{ {
_appNameLabel.Text = "Welcome to UpTool2"; _appNameLabel.Text = "Welcome to UpTool2";
_appNameLabel.Enabled = false;
_appDescriptionLabel.Text = "Select an app to get started"; _appDescriptionLabel.Text = "Select an app to get started";
_appControls.Clear();
} }
} }
} }

View File

@ -1,32 +1,34 @@
using System.Collections.Generic;
using Eto.Drawing; using Eto.Drawing;
using Eto.Forms; using Eto.Forms;
using UpToolEto.Controls; using UpToolEto.Controls;
using UpToolLib; using UpToolLib;
using UpToolLib.DataStructures; using UpToolLib.DataStructures;
using UpToolLib.v2.TaskQueue;
//TODO implement tasks queue UI //TODO implement tasks queue UI and add control to execute queue, also needs to clear AppPanel and reload AppList
//TODO keep track of app state //TODO add control_upload
//TODO app filters (search by name/tags)
//TODO add control_upload action_run action_update action_remove action_install
namespace UpToolEto.Forms namespace UpToolEto.Forms
{ {
public partial class MainForm : Form public partial class MainForm : Form
{ {
private readonly AppPanel _appPanel; private readonly AppPanel _appPanel;
private readonly IList<AppTask> _tasks;
public MainForm(InitScreen init, UpToolLibMain lib, IExternalFunctionality platform, bool online) public MainForm(InitScreen init, UpToolLibMain lib, IExternalFunctionality platform, bool online)
{ {
_tasks = new List<AppTask>();
Title = "UpTool2"; Title = "UpTool2";
MinimumSize = new Size(600, 100); MinimumSize = new Size(600, 100);
AppList appList = new(lib.V1.Apps, (guid, app) => _appPanel.FromApp(app)); AppList appList = new(lib.V1.AppExtras, (_, app) => _appPanel.SetApp(app), online);
_appPanel = new AppPanel(); _appPanel = new AppPanel(lib.V2.TaskFactory, lib.V1.AppExtras, _tasks);
Content = new StackLayout Content = new StackLayout
{ {
Padding = 10, Padding = 10,
Items = Items =
{ {
appList, new StackLayoutItem(appList, VerticalAlignment.Stretch),
new StackLayoutItem(_appPanel, true) new StackLayoutItem(_appPanel, VerticalAlignment.Stretch, true)
}, },
Orientation = Orientation.Horizontal Orientation = Orientation.Horizontal
}; };

View File

@ -20,17 +20,17 @@ namespace UpToolEto
public class Main public class Main
{ {
private readonly IExternalFunctionality _platform; private readonly IExternalFunctionality _platform;
private readonly UpToolLibMain _lib;
private readonly Application _application; private readonly Application _application;
private readonly Action _activityExistsException; private readonly Action _activityExistsException;
private readonly InitScreen _init; private readonly InitScreen _init;
private readonly bool _skipFetch; private readonly bool _skipFetch;
public static bool DebugColors { get; private set; }
public Main(Application application, Action activityExistsException, string[] args) public Main(Application application, Action activityExistsException, string[] args)
{ {
_skipFetch = args.Contains("--skip-fetch"); _skipFetch = args.Contains("--skip-fetch");
DebugColors = args.Contains("--debug-colors");
_platform = new UTLibFunctions(application); _platform = new UTLibFunctions(application);
_lib = new UpToolLibMain(_platform);
_application = application; _application = application;
_activityExistsException = activityExistsException; _activityExistsException = activityExistsException;
_init = new(application, _platform); _init = new(application, _platform);
@ -44,40 +44,41 @@ namespace UpToolEto
private void InitThread() private void InitThread()
{ {
UpToolLibMain lib = null;
try try
{ {
lib = new UpToolLibMain(_platform);
_init.SetText("Initializing paths"); _init.SetText("Initializing paths");
if (!Directory.Exists(_lib.V1.PathTool.Dir)) if (!Directory.Exists(lib.V1.PathTool.Dir))
Directory.CreateDirectory(_lib.V1.PathTool.Dir); Directory.CreateDirectory(lib.V1.PathTool.Dir);
FixXml(_lib.V1.XmlTool, _lib.V1.PathTool); FixXml(lib.V1.XmlTool, lib.V1.PathTool);
_init.SetText("Performing checks"); _init.SetText("Performing checks");
bool online = false; bool online = false;
UpdateCheck updateCheck = null; UpdateCheck updateCheck = null;
try try
{ {
updateCheck = _lib.V2.UpdateChecker.Check(); updateCheck = lib.V2.UpdateChecker.Check();
online = true; online = true;
} }
catch catch
{ {
_platform.Log("Could not perform update check, starting offline"); _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"); _platform.Log("Quitting");
_application.Quit(); else
return;
}
if (!Directory.Exists(_lib.V1.PathTool.GetRelative("Apps")))
Directory.CreateDirectory(_lib.V1.PathTool.GetRelative("Apps"));
if (!_skipFetch && online)
{ {
_init.SetText("Fetching repos"); if (!Directory.Exists(lib.V1.PathTool.GetRelative("Apps")))
_lib.V2.RepoManagement.FetchRepos(); 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) catch (MutexLockLockedException)
{ {
@ -90,11 +91,13 @@ namespace UpToolEto
} }
catch (Exception e) catch (Exception e)
{ {
lib?.Dispose();
_platform.Log(e.ToString()); _platform.Log(e.ToString());
} }
finally finally
{ {
_lib?.Dispose(); lib?.Dispose();
_application.Invoke(() => _application.Quit());
} }
} }

View File

@ -9,6 +9,11 @@ namespace UpToolLib.DataStructures
Updatable = 2, Updatable = 2,
Installed = 4, Installed = 4,
Local = 8, Local = 8,
All = 15 All = 0
}
public static class StatusExtensions
{
public static bool Contains(this Status status, Status other) => (status & other) == other;
} }
} }

View File

@ -108,6 +108,8 @@ namespace UpToolLib.v1.Tool
public App[] FindApps(string identifier) public App[] FindApps(string identifier)
{ {
if (string.IsNullOrWhiteSpace(identifier))
return _apps.Values.ToArray();
IEnumerable<KeyValuePair<Guid, App>> tmp1 = _apps.Where(s => s.Key.ToString().StartsWith(identifier)); IEnumerable<KeyValuePair<Guid, App>> 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.Name.Contains(identifier)));
tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Description.Contains(identifier))); tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Description.Contains(identifier)));