Create local repo when fetching Apps

This commit is contained in:
CreepyCrafter24 2019-10-20 15:18:21 +02:00
parent c91573cff9
commit be9f76879c
5 changed files with 213 additions and 176 deletions

View File

@ -12,3 +12,4 @@
- __APPFILES - __APPFILES
- info.xml - info.xml
- Version - Version
- Repo

View File

@ -2,3 +2,4 @@ More Icons for Apps
More apps: Laptop Sim (when done) More apps: Laptop Sim (when done)
Use local info when building GUI (Except name/description) Use local info when building GUI (Except name/description)
Decent updater Decent updater
Do not refetch Repos after install/update (save local repo in main info.xml)

View File

@ -13,7 +13,6 @@ namespace UpTool2
{ {
public partial class DownloadDialog : Form public partial class DownloadDialog : Form
{ {
WebClient client;
bool close; bool close;
public DownloadDialog(string uri, string file) public DownloadDialog(string uri, string file)
{ {

View File

@ -16,173 +16,7 @@ namespace UpTool2
{ {
public partial class MainForm : Form public partial class MainForm : Form
{ {
Dictionary<Guid, App> apps = new Dictionary<Guid, App>(); #region Install/Remove/Upload (Main local app management)
enum Status { Not_Installed = 1, Updatable = 2, Installed = 4, Local = 8, All = 15 }
string dir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\UpTool2";
public MainForm()
{
InitializeComponent();
filterBox.DataSource = Enum.GetValues(typeof(Status));
reloadElements();
if (!Directory.Exists(dir + @"\Apps"))
Directory.CreateDirectory(dir + @"\Apps");
}
private void MainForm_Load(object sender, EventArgs e)
{
Program.splash.Hide();
BringToFront();
}
void reloadElements()
{
//remove
toolTip.RemoveAll();
clearSelection();
infoPanel_Title.Invalidate();
infoPanel_Description.Invalidate();
int F = sidebarPanel.Controls.Count;
for (int i = 0; i < F; i++)
{
sidebarPanel.Controls[0].Dispose();
}
apps.Clear();
//add
toolTip.SetToolTip(controls_settings, "Settings");
toolTip.SetToolTip(controls_reload, "Refresh repositories");
toolTip.SetToolTip(controls_upload, "Install package from disk");
toolTip.SetToolTip(filterBox, "Filter");
toolTip.SetToolTip(action_install, "Install");
toolTip.SetToolTip(action_remove, "Remove");
toolTip.SetToolTip(action_update, "Update");
toolTip.SetToolTip(action_run, "Run");
WebClient client = new WebClient();
for (int i = 0; i < Settings.Default.Repos.Count; i++)
{
#if !DEBUG
try
{
#endif
//get info
XDocument repo = XDocument.Load(Settings.Default.Repos[i]);
foreach (XElement el in repo.Element("repo").Elements("app"))
{
int version = int.Parse(el.Element("Version").Value);
Guid ID = Guid.Parse(el.Element("ID").Value);
if (!(apps.ContainsKey(ID) && apps[ID].version >= version))
{
string name = el.Element("Name").Value;
string description = el.Element("Description").Value;
string file = el.Element("File").Value;
string hash = el.Element("Hash").Value;
bool runnable = el.Element("MainFile") != null;
string mainFile = "";
if (runnable)
mainFile = el.Element("MainFile").Value;
Color color = ColorTranslator.FromHtml(el.Element("Color").Value);
Image icon = el.Element("Icon") == null ? Resources.C_64.ToBitmap() : Image.FromStream(client.OpenRead(el.Element("Icon").Value));
apps[ID] = new App(name, description, version, file, false, hash, ID, color, icon, runnable, mainFile);
}
}
#if !DEBUG
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Failed to load repo: " + Settings.Default.Repos[i]);
}
#endif
}
string[] localApps = Directory.GetDirectories(dir + @"\Apps\");
for (int i = 0; i < localApps.Length; i++)
{
Guid tmp = Guid.Parse(Path.GetFileName(localApps[i]));
if (!apps.ContainsKey(tmp))
{
XElement data = XDocument.Load(dir + @"\Apps\" + tmp.ToString() + @"\info.xml").Element("app");
apps.Add(tmp, new App("(local) " + data.Element("Name").Value, data.Element("Description").Value, -1, "", true, "", tmp, Color.Red, Resources.C_64.ToBitmap(), data.Element("MainFile") != null, data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
}
List<App> tmp_appslist = new List<App>(apps.Values);
tmp_appslist.Sort((x, y) => x.name.CompareTo(y.name));
foreach ((App app, Panel sidebarIcon) in from App app in tmp_appslist let sidebarIcon = new Panel() select (app, sidebarIcon))
{
sidebarIcon.Tag = app;
sidebarIcon.BackColor = app.color;
sidebarIcon.Size = new Size(70, 70);
sidebarIcon.BackgroundImage = app.icon;
sidebarIcon.BackgroundImageLayout = ImageLayout.Stretch;
sidebarIcon.Click += (object sender, EventArgs e) => {
infoPanel_Title.Text = app.name;
infoPanel_Title.ForeColor = app.local ? Color.Red : Color.Black;
infoPanel_Description.Text = app.description;
action_install.Tag = app;
action_install.Enabled = !(app.local || Directory.Exists(dir + @"\Apps\" + app.ID.ToString()));
action_remove.Tag = app;
action_remove.Enabled = Directory.Exists(dir + @"\Apps\" + app.ID.ToString());
action_update.Tag = app;
string xml = dir + @"\Apps\" + app.ID.ToString() + @"\info.xml";
action_update.Enabled = (!app.local) && File.Exists(xml) && int.Parse(XDocument.Load(xml).Element("app").Element("Version").Value) < app.version;
action_run.Tag = app;
action_run.Enabled = (!app.local) && app.runnable && Directory.Exists(dir + @"\Apps\" + app.ID.ToString());
};
toolTip.SetToolTip(sidebarIcon, app.name);
sidebarPanel.Controls.Add(sidebarIcon);
}
client.Dispose();
updateSidebarV(null, null);
}
private void Controls_settings_Click(object sender, EventArgs e) => new SettingsForm().Show();
private void Controls_reload_Click(object sender, EventArgs e) => reloadElements();
private void Action_run_Click(object sender, EventArgs e)
{
string app = dir + @"\Apps\" + ((App)action_run.Tag).ID.ToString();
Process.Start(new ProcessStartInfo { FileName = app + "\\app\\" + ((App)action_run.Tag).mainFile, WorkingDirectory = app + @"\app" });
}
bool relE = true;
private void Action_remove_Click(object sender, EventArgs e)
{
try
{
string app = dir + @"\Apps\" + ((App)action_remove.Tag).ID.ToString();
string tmp = dir + @"\tmp";
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
ZipFile.ExtractToDirectory(app + @"\package.zip", tmp);
Process.Start(new ProcessStartInfo { FileName = "cmd.exe", Arguments = "/C \"" + tmp + "\\Remove.bat\"", WorkingDirectory = app + @"\app" }).WaitForExit();
Directory.Delete(tmp, true);
Directory.Delete(app, true);
if (relE)
reloadElements();
}
catch (Exception e1)
{
if (!relE)
throw;
MessageBox.Show(e1.ToString(), "Removal failed");
}
}
private void Action_update_Click(object sender, EventArgs e)
{
try
{
relE = false;
Action_remove_Click(sender, e);
Action_install_Click(sender, e);
}
catch (Exception e1)
{
MessageBox.Show(e1.ToString(), "Install failed");
}
reloadElements();
relE = true;
}
private void Action_install_Click(object sender, EventArgs e) private void Action_install_Click(object sender, EventArgs e)
{ {
string app = ""; string app = "";
@ -220,7 +54,29 @@ namespace UpTool2
#endif #endif
Directory.Delete(tmp, true); Directory.Delete(tmp, true);
} }
private void Action_remove_Click(object sender, EventArgs e)
{
try
{
string app = dir + @"\Apps\" + ((App)action_remove.Tag).ID.ToString();
string tmp = dir + @"\tmp";
if (Directory.Exists(tmp))
Directory.Delete(tmp, true);
Directory.CreateDirectory(tmp);
ZipFile.ExtractToDirectory(app + @"\package.zip", tmp);
Process.Start(new ProcessStartInfo { FileName = "cmd.exe", Arguments = "/C \"" + tmp + "\\Remove.bat\"", WorkingDirectory = app + @"\app" }).WaitForExit();
Directory.Delete(tmp, true);
Directory.Delete(app, true);
if (relE)
reloadElements();
}
catch (Exception e1)
{
if (!relE)
throw;
MessageBox.Show(e1.ToString(), "Removal failed");
}
}
private void controls_upload_Click(object sender, EventArgs e) private void controls_upload_Click(object sender, EventArgs e)
{ {
string app = ""; string app = "";
@ -261,7 +117,6 @@ namespace UpTool2
if (tmp != "" && Directory.Exists(tmp)) if (tmp != "" && Directory.Exists(tmp))
Directory.Delete(tmp, true); Directory.Delete(tmp, true);
} }
void completeInstall(string app, App appI) void completeInstall(string app, App appI)
{ {
try try
@ -279,7 +134,165 @@ namespace UpTool2
} }
catch { throw; } catch { throw; }
} }
#endregion
#region Repo management
void reloadElements()
{
//remove
toolTip.RemoveAll();
clearSelection();
infoPanel_Title.Invalidate();
infoPanel_Description.Invalidate();
int F = sidebarPanel.Controls.Count;
for (int i = 0; i < F; i++)
{
sidebarPanel.Controls[0].Dispose();
}
apps.Clear();
//add
toolTip.SetToolTip(controls_settings, "Settings");
toolTip.SetToolTip(controls_reload, "Refresh repositories");
toolTip.SetToolTip(controls_upload, "Install package from disk");
toolTip.SetToolTip(filterBox, "Filter");
toolTip.SetToolTip(action_install, "Install");
toolTip.SetToolTip(action_remove, "Remove");
toolTip.SetToolTip(action_update, "Update");
toolTip.SetToolTip(action_run, "Run");
getLiveRepos();
foreach (App app in apps.Values)
{
Panel sidebarIcon = new Panel();
sidebarIcon.Tag = app;
sidebarIcon.BackColor = app.color;
sidebarIcon.Size = new Size(70, 70);
sidebarIcon.BackgroundImage = app.icon;
sidebarIcon.BackgroundImageLayout = ImageLayout.Stretch;
sidebarIcon.Click += (object sender, EventArgs e) => {
infoPanel_Title.Text = app.name;
infoPanel_Title.ForeColor = app.local ? Color.Red : Color.Black;
infoPanel_Description.Text = app.description;
action_install.Tag = app;
action_install.Enabled = !(app.local || Directory.Exists(dir + @"\Apps\" + app.ID.ToString()));
action_remove.Tag = app;
action_remove.Enabled = Directory.Exists(dir + @"\Apps\" + app.ID.ToString());
action_update.Tag = app;
string xml = dir + @"\Apps\" + app.ID.ToString() + @"\info.xml";
action_update.Enabled = (!app.local) && File.Exists(xml) && int.Parse(XDocument.Load(xml).Element("app").Element("Version").Value) < app.version;
action_run.Tag = app;
action_run.Enabled = (!app.local) && app.runnable && Directory.Exists(dir + @"\Apps\" + app.ID.ToString());
};
toolTip.SetToolTip(sidebarIcon, app.name);
sidebarPanel.Controls.Add(sidebarIcon);
}
updateSidebarV(null, null);
}
void getLiveRepos()
{
List<App> tmp_appslist = fetchRepos();
apps.Clear();
tmp_appslist.ForEach(s => apps.Add(s.ID, s));
}
List<App> fetchRepos()
{
WebClient client = new WebClient();
for (int i = 0; i < Settings.Default.Repos.Count; i++)
{
#if !DEBUG
try
{
#endif
XDocument repo = XDocument.Load(Settings.Default.Repos[i]);
foreach (XElement el in repo.Element("repo").Elements("app"))
{
int version = int.Parse(el.Element("Version").Value);
Guid ID = Guid.Parse(el.Element("ID").Value);
if (!(apps.ContainsKey(ID) && apps[ID].version >= version))
{
string name = el.Element("Name").Value;
string description = el.Element("Description").Value;
string file = el.Element("File").Value;
string hash = el.Element("Hash").Value;
bool runnable = el.Element("MainFile") != null;
string mainFile = "";
if (runnable)
mainFile = el.Element("MainFile").Value;
Color color = ColorTranslator.FromHtml(el.Element("Color").Value);
Image icon = el.Element("Icon") == null ? Resources.C_64.ToBitmap() : Image.FromStream(client.OpenRead(el.Element("Icon").Value));
App tmp_app = new App(name, description, version, file, false, hash, ID, color, icon, runnable, mainFile);
if (el.Element("Icon") != null)
tmp_app.tag = el.Element("Icon").Value;
apps[ID] = tmp_app;
}
}
#if !DEBUG
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Failed to load repo: " + Settings.Default.Repos[i]);
}
#endif
client.Dispose();
}
string[] localApps = Directory.GetDirectories(dir + @"\Apps\");
for (int i = 0; i < localApps.Length; i++)
{
Guid tmp = Guid.Parse(Path.GetFileName(localApps[i]));
if (!apps.ContainsKey(tmp))
{
XElement data = XDocument.Load(dir + @"\Apps\" + tmp.ToString() + @"\info.xml").Element("app");
apps.Add(tmp, new App("(local) " + data.Element("Name").Value, data.Element("Description").Value, -1, "", true, "", tmp, Color.Red, Resources.C_64.ToBitmap(), data.Element("MainFile") != null, data.Element("MainFile") == null ? "" : data.Element("MainFile").Value));
}
}
List<App> tmp_appslist = new List<App>(apps.Values);
tmp_appslist.Sort((x, y) => x.name.CompareTo(y.name));
string xml = dir + @"\info.xml";
XElement meta = XDocument.Load(xml).Element("meta");
if (meta.Element("Repo") == null)
meta.Add(new XElement("Repo"));
meta.Save(xml);
XElement repos = meta.Element("Repo");
repos.RemoveNodes();
tmp_appslist.ForEach(app => {
XElement el = new XElement(app.ID.ToString(),
new XElement("Name", app.name),
new XElement("Description", app.description),
new XElement("Version", app.version),
new XElement("File", app.file),
new XElement("Hash", app.hash),
new XElement("MainFile", app.mainFile),
new XElement("Color", string.Format("{0:x6}", app.color.ToArgb() & 0xFFFFFF)));
repos.Add(el);
if (app.tag != null)
el.Add(new XElement("Icon", (string)app.tag));
});
meta.Save(xml);
return tmp_appslist;
}
#endregion
#region Run/Update/Reload/Settings (Small links to other stuff)
private void Action_run_Click(object sender, EventArgs e) => _ = Process.Start(new ProcessStartInfo { FileName = getDataPath((App)action_run.Tag) + "\\" + ((App)action_run.Tag).mainFile, WorkingDirectory = getDataPath((App)action_run.Tag) });
private void Action_update_Click(object sender, EventArgs e)
{
try
{
relE = false;
Action_remove_Click(sender, e);
Action_install_Click(sender, e);
}
catch (Exception e1)
{
MessageBox.Show(e1.ToString(), "Install failed");
}
reloadElements();
relE = true;
}
private void Controls_reload_Click(object sender, EventArgs e) => reloadElements();
private void Controls_settings_Click(object sender, EventArgs e) => new SettingsForm().Show();
#endregion
#region GUI (stuff only present for GUI)
void clearSelection() void clearSelection()
{ {
action_install.Enabled = false; action_install.Enabled = false;
@ -289,7 +302,6 @@ namespace UpTool2
infoPanel_Title.Text = ""; infoPanel_Title.Text = "";
infoPanel_Description.Text = ""; infoPanel_Description.Text = "";
} }
private void updateSidebarV(object sender, EventArgs e) private void updateSidebarV(object sender, EventArgs e)
{ {
Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status); Enum.TryParse(filterBox.SelectedValue.ToString(), out Status status);
@ -301,7 +313,21 @@ namespace UpTool2
} }
clearSelection(); clearSelection();
} }
public MainForm()
{
InitializeComponent();
filterBox.DataSource = Enum.GetValues(typeof(Status));
reloadElements();
if (!Directory.Exists(appsPath))
Directory.CreateDirectory(appsPath);
}
private void MainForm_Load(object sender, EventArgs e)
{
Program.splash.Hide();
BringToFront();
}
#endregion
#region Definitions
private struct App : IEquatable<App> private struct App : IEquatable<App>
{ {
public string name; public string name;
@ -315,8 +341,9 @@ namespace UpTool2
public Image icon; public Image icon;
public bool runnable; public bool runnable;
public string mainFile; public string mainFile;
public object tag;
public App(string name, string description, int version, string file, bool local, string hash, Guid iD, Color color, Image icon, bool runnable, string mainFile) public App(string name, string description, int version, string file, bool local, string hash, Guid iD, Color color, Image icon, bool runnable, string mainFile, object tag = null)
{ {
this.name = name ?? throw new ArgumentNullException(nameof(name)); this.name = name ?? throw new ArgumentNullException(nameof(name));
this.description = description ?? throw new ArgumentNullException(nameof(description)); this.description = description ?? throw new ArgumentNullException(nameof(description));
@ -329,6 +356,7 @@ namespace UpTool2
this.icon = icon ?? throw new ArgumentNullException(nameof(icon)); this.icon = icon ?? throw new ArgumentNullException(nameof(icon));
this.runnable = runnable; this.runnable = runnable;
this.mainFile = mainFile ?? throw new ArgumentNullException(nameof(mainFile)); this.mainFile = mainFile ?? throw new ArgumentNullException(nameof(mainFile));
this.tag = tag;
} }
public Status status public Status status
@ -356,5 +384,13 @@ namespace UpTool2
public static bool operator ==(App left, App right) => left.Equals(right); public static bool operator ==(App left, App right) => left.Equals(right);
public static bool operator !=(App left, App right) => !(left == right); public static bool operator !=(App left, App right) => !(left == right);
} }
Dictionary<Guid, App> apps = new Dictionary<Guid, App>();
enum Status { Not_Installed = 1, Updatable = 2, Installed = 4, Local = 8, All = 15 }
string dir => Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\UpTool2";
string appsPath => dir + @"\Apps";
string getAppPath(App app) => appsPath + @"\" + app.ID.ToString();
string getDataPath(App app) => getAppPath(app) + @"\app";
bool relE = true;
#endregion
} }
} }

View File

@ -80,7 +80,7 @@ namespace UpTool2
Directory.CreateDirectory(dir + @"\Apps"); Directory.CreateDirectory(dir + @"\Apps");
string xml = dir + @"\info.xml"; string xml = dir + @"\info.xml";
if (!File.Exists(xml)) if (!File.Exists(xml))
new XElement("meta", new XElement("Version", 0)).Save(xml); new XElement("meta", new XElement("Version", 0), new XElement("Repo")).Save(xml);
XElement meta = XDocument.Load("https://github.com/CreepyCrafter24/UpTool2/releases/download/Repo/Meta.xml").Element("meta"); XElement meta = XDocument.Load("https://github.com/CreepyCrafter24/UpTool2/releases/download/Repo/Meta.xml").Element("meta");
int version = int.Parse(meta.Element("Version").Value); int version = int.Parse(meta.Element("Version").Value);
if (int.Parse(XDocument.Load(xml).Element("meta").Element("Version").Value) < version) if (int.Parse(XDocument.Load(xml).Element("meta").Element("Version").Value) < version)