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,
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();
}

View File

@ -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<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();
int updatableCount = apps.Count();
Console.WriteLine(updatableCount == 0

View File

@ -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<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}");
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 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<Guid, App> _apps;
private readonly AppExtras _extras;
private readonly Action<Guid, App> _itemClickEvent;
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;
_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,
});
}
}
}

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.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<AppTask> 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();
}
}
}

View File

@ -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<AppTask> _tasks;
public MainForm(InitScreen init, UpToolLibMain lib, IExternalFunctionality platform, bool online)
{
_tasks = new List<AppTask>();
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
};

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -108,6 +108,8 @@ namespace UpToolLib.v1.Tool
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));
tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Name.Contains(identifier)));
tmp1 = tmp1.Concat(_apps.Where(s => s.Value.Description.Contains(identifier)));