livebook/rel/app/windows/Livebook.cs

154 lines
3.9 KiB
C#

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
#nullable enable
namespace Livebook;
static class LivebookMain
{
[STAThread]
static void Main(string[] args)
{
var prefix = "open:";
var url = "";
if (args.Length == 1 && args[0].StartsWith(prefix))
{
var uri = new System.Uri(args[0].Remove(0, prefix.Length));
url = uri.AbsoluteUri;
}
var logPath = getLogPath();
if (ElixirKit.API.IsMainInstance("dev.livebook.Livebook"))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LivebookApp(url, logPath));
var code = ElixirKit.API.Stop();
if (code == 0) { return; }
var message = $"Livebook exited with exit code {code}.\r\nLogs available at: {logPath}";
MessageBox.Show(new Form() { TopMost = true }, message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
ElixirKit.API.Publish("open", url);
}
}
internal static string getLogPath()
{
return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Livebook",
"Logs",
"Livebook.log"
);
}
}
class DummyForm : Form {}
class LivebookApp : ApplicationContext
{
private NotifyIcon notifyIcon;
private string? url;
private string logPath;
public LivebookApp(string url, string logPath)
{
this.logPath = logPath;
ThreadExit += threadExit;
ContextMenuStrip menu = new ContextMenuStrip();
menu.Items.Add("Open", null, openClicked);
var copyURLButton = menu.Items.Add("Copy URL", null, copyURLClicked);
copyURLButton.Enabled = false;
menu.Items.Add("View Logs", null, viewLogsClicked);
menu.Items.Add("Settings", null, openSettingsClicked);
menu.Items.Add("Quit", null, quitClicked);
notifyIcon = new NotifyIcon()
{
Text = "Livebook",
Visible = true,
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath)!,
ContextMenuStrip = menu
};
notifyIcon.Click += notifyIconClicked;
Directory.CreateDirectory(Path.GetDirectoryName(logPath)!);
ElixirKit.API.Start(
name: "app",
logPath: logPath,
exited: (exitCode) =>
{
Application.Exit();
}
);
ElixirKit.API.Subscribe((name, data) =>
{
switch (name)
{
case "url":
copyURLButton.Enabled = true;
this.url = data;
break;
default:
throw new Exception($"unknown event {name}");
}
});
ElixirKit.API.Publish("open", url);
}
private void threadExit(object? sender, EventArgs e)
{
notifyIcon.Visible = false;
}
private void notifyIconClicked(object? sender, EventArgs e)
{
MouseEventArgs mouseEventArgs = (MouseEventArgs)e;
if (mouseEventArgs.Button == MouseButtons.Left)
{
ElixirKit.API.Publish("open", "");
}
}
private void openClicked(object? sender, EventArgs e)
{
ElixirKit.API.Publish("open", "");
}
private void copyURLClicked(object? sender, EventArgs e)
{
System.Windows.Forms.Clipboard.SetText(url!);
}
private void viewLogsClicked(object? sender, EventArgs e)
{
System.Diagnostics.Process.Start(logPath);
}
private void openSettingsClicked(object? sender, EventArgs e)
{
ElixirKit.API.Publish("open", "/settings");
}
private void quitClicked(object? sender, EventArgs e)
{
notifyIcon.Visible = false;
Application.Exit();
}
}