mirror of
https://github.com/netchx/netch.git
synced 2026-05-01 22:19:37 +08:00
Fix active/save Profile
Fix SingleInstance MainForm Refactors
This commit is contained in:
@@ -32,7 +32,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
using var releaser = await Lock.EnterAsync();
|
||||
|
||||
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.Remark}");
|
||||
Log.Information("Start MainController: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.i18NRemark}");
|
||||
|
||||
if (await DnsUtils.LookupAsync(server.Hostname) == null)
|
||||
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
|
||||
|
||||
@@ -66,13 +66,20 @@ namespace Netch.Forms
|
||||
_parent.LocationChanged += Parent_Move;
|
||||
_parent.SizeChanged += Parent_Move;
|
||||
_parent.Activated += Parent_Activated;
|
||||
_parent.VisibleChanged += Parent_VisibleChanged;
|
||||
}
|
||||
|
||||
private void Parent_VisibleChanged(object? sender, EventArgs e)
|
||||
{
|
||||
Visible = _parent.Visible;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs? e)
|
||||
{
|
||||
_parent.Activated -= Parent_Activated;
|
||||
_parent.LocationChanged -= Parent_Move;
|
||||
_parent.SizeChanged -= Parent_Move;
|
||||
_parent.Activated -= Parent_Activated;
|
||||
_parent.VisibleChanged -= Parent_VisibleChanged;
|
||||
base.OnClosing(e!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -884,83 +884,54 @@ namespace Netch.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void ActiveProfile(Profile profile)
|
||||
{
|
||||
ProfileNameText.Text = profile.ProfileName;
|
||||
|
||||
var server = ServerComboBox.Items.Cast<Server>().FirstOrDefault(s => s.Remark.Equals(profile.ServerRemark));
|
||||
var mode = ModeComboBox.Items.Cast<Mode>().FirstOrDefault(m => m.Remark.Equals(profile.ModeRemark));
|
||||
|
||||
if (server == null)
|
||||
throw new Exception("Server not found.");
|
||||
|
||||
if (mode == null)
|
||||
throw new Exception("Mode not found.");
|
||||
|
||||
ServerComboBox.SelectedItem = server;
|
||||
ModeComboBox.SelectedItem = mode;
|
||||
}
|
||||
|
||||
private Profile CreateProfileAtIndex(int index)
|
||||
{
|
||||
var server = (Server)ServerComboBox.SelectedItem;
|
||||
var mode = (Mode)ModeComboBox.SelectedItem;
|
||||
var name = ProfileNameText.Text;
|
||||
|
||||
Profile? profile;
|
||||
if ((profile = Global.Settings.Profiles.SingleOrDefault(p => p.Index == index)) != null)
|
||||
Global.Settings.Profiles.Remove(profile);
|
||||
|
||||
profile = new Profile(server, mode, name, index);
|
||||
Global.Settings.Profiles.Add(profile);
|
||||
return profile;
|
||||
}
|
||||
|
||||
private async void ProfileButton_Click([NotNull] object? sender, EventArgs? e)
|
||||
{
|
||||
if (sender == null)
|
||||
throw new ArgumentNullException(nameof(sender));
|
||||
throw new InvalidOperationException();
|
||||
|
||||
var profileButton = (Button)sender;
|
||||
var profile = (Profile?)profileButton.Tag;
|
||||
var index = ProfileTable.Controls.IndexOf(profileButton);
|
||||
var button = (Button)sender;
|
||||
var profile = (Profile?)button.Tag;
|
||||
var index = ProfileTable.Controls.IndexOf(button);
|
||||
|
||||
switch (ModifierKeys)
|
||||
{
|
||||
case Keys.Control:
|
||||
if (ServerComboBox.SelectedIndex == -1)
|
||||
// Save Profile
|
||||
if (ServerComboBox.SelectedItem is not Server server)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ModeComboBox.SelectedIndex == -1)
|
||||
if (ModeComboBox.SelectedItem is not Mode mode)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ProfileNameText.Text == "")
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please enter a profile name first"));
|
||||
ProfileNameText.Focus();
|
||||
return;
|
||||
}
|
||||
var name = ProfileNameText.Text;
|
||||
|
||||
Global.Settings.Profiles.RemoveAll(p => p.Index == index);
|
||||
profile = new Profile(server, mode, name, index);
|
||||
Global.Settings.Profiles.Add(profile);
|
||||
button.Tag = profile;
|
||||
button.Text = profile.ProfileName;
|
||||
|
||||
profileButton.Tag = profile = CreateProfileAtIndex(index);
|
||||
profileButton.Text = profile.ProfileName;
|
||||
ProfileNameText.Clear();
|
||||
return;
|
||||
case Keys.Shift:
|
||||
// Delete Profile
|
||||
if (profile == null)
|
||||
return;
|
||||
|
||||
Global.Settings.Profiles.Remove(profile);
|
||||
profileButton.Tag = null;
|
||||
profileButton.Text = i18N.Translate("None");
|
||||
button.Tag = null;
|
||||
button.Text = i18N.Translate("None");
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate Profile
|
||||
|
||||
if (profile == null)
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("No saved profile here. Save a profile first by Ctrl+Click on the button"));
|
||||
@@ -969,23 +940,29 @@ namespace Netch.Forms
|
||||
|
||||
try
|
||||
{
|
||||
ActiveProfile(profile);
|
||||
ProfileNameText.Text = profile.ProfileName;
|
||||
|
||||
var server = ServerComboBox.Items.Cast<Server>().FirstOrDefault(s => s.Remark.Equals(profile.ServerRemark));
|
||||
var mode = ModeComboBox.Items.Cast<Mode>().FirstOrDefault(m => m.Remark.Any(s => s.Value.Equals(profile.ModeRemark)));
|
||||
|
||||
if (server == null)
|
||||
throw new MessageException("Server not found.");
|
||||
|
||||
if (mode == null)
|
||||
throw new MessageException("Mode not found.");
|
||||
|
||||
// set active server and mode
|
||||
ServerComboBox.SelectedItem = server;
|
||||
ModeComboBox.SelectedItem = mode;
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch (MessageException exception)
|
||||
{
|
||||
MessageBoxX.Show(exception.Message, LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// start the profile
|
||||
ControlButton_Click(null, null);
|
||||
if (State == State.Stopping || State == State.Stopped)
|
||||
{
|
||||
while (State != State.Stopped)
|
||||
await Task.Delay(250);
|
||||
|
||||
ControlButton_Click(null, null);
|
||||
}
|
||||
await StopAsync();
|
||||
ControlButton.PerformClick();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1259,7 +1236,7 @@ namespace Netch.Forms
|
||||
|
||||
private bool _resumeFlag;
|
||||
|
||||
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
{
|
||||
switch (e.Mode)
|
||||
{
|
||||
@@ -1268,7 +1245,7 @@ namespace Netch.Forms
|
||||
{
|
||||
_resumeFlag = true;
|
||||
Log.Information("OS Suspend, Stop");
|
||||
ControlButton_Click(null, null);
|
||||
await StopAsync();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1277,7 +1254,7 @@ namespace Netch.Forms
|
||||
{
|
||||
_resumeFlag = false;
|
||||
Log.Information("OS Resume, Restart");
|
||||
ControlButton_Click(null, null);
|
||||
ControlButton.PerformClick();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1307,7 +1284,7 @@ namespace Netch.Forms
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please press Stop button first"));
|
||||
|
||||
NotifyIcon_MouseDoubleClick(null, null);
|
||||
ShowMainFormToolStripButton.PerformClick();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1417,26 +1394,9 @@ namespace Netch.Forms
|
||||
|
||||
#region NotifyIcon
|
||||
|
||||
public void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
|
||||
private void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => ShowMainFormToolStripButton_Click(sender, e)));
|
||||
return;
|
||||
}
|
||||
|
||||
var forms = Application.OpenForms.Cast<Form>().ToList();
|
||||
var anyWindowOpened = forms.Any(f => f is not (MainForm or LogForm));
|
||||
|
||||
forms.ForEach(f =>
|
||||
{
|
||||
if (anyWindowOpened && f is MainForm or LogForm)
|
||||
return;
|
||||
|
||||
f.Show();
|
||||
f.WindowState = FormWindowState.Normal;
|
||||
f.Activate();
|
||||
});
|
||||
Utils.Utils.ActivateVisibleWindows();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -27,24 +27,29 @@ namespace Netch
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Program)}");
|
||||
public static readonly SingleInstanceService SingleInstance = new($"Global\\{nameof(Netch)}");
|
||||
|
||||
internal static HWND ConsoleHwnd { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点
|
||||
/// </summary>
|
||||
#pragma warning disable VSTHRD002
|
||||
// VSTHRD002: Avoid problematic synchronous waits
|
||||
// Main never re-called, so we can ignore this
|
||||
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// handle arguments
|
||||
if (args.Contains(Constants.Parameter.ForceUpdate))
|
||||
Flags.AlwaysShowNewVersionFound = true;
|
||||
|
||||
// 设置当前目录
|
||||
// set working directory
|
||||
Directory.SetCurrentDirectory(Global.NetchDir);
|
||||
|
||||
// append .\bin to PATH
|
||||
var binPath = Path.Combine(Global.NetchDir, "bin");
|
||||
Environment.SetEnvironmentVariable("PATH", $"{Environment.GetEnvironmentVariable("PATH")};{binPath}");
|
||||
|
||||
// check if .\bin directory exists
|
||||
if (!Directory.Exists("bin") || !Directory.EnumerateFileSystemEntries("bin").Any())
|
||||
{
|
||||
i18N.Load("System");
|
||||
@@ -52,19 +57,19 @@ namespace Netch
|
||||
Environment.Exit(2);
|
||||
}
|
||||
|
||||
// clean up old files
|
||||
Updater.CleanOld(Global.NetchDir);
|
||||
|
||||
// 预创建目录
|
||||
// pre-create directories
|
||||
var directories = new[] { "mode\\Custom", "data", "i18n", "logging" };
|
||||
foreach (var item in directories)
|
||||
if (!Directory.Exists(item))
|
||||
Directory.CreateDirectory(item);
|
||||
|
||||
// 加载配置
|
||||
#pragma warning disable VSTHRD002
|
||||
// load configuration
|
||||
Configuration.LoadAsync().Wait();
|
||||
#pragma warning restore VSTHRD002
|
||||
|
||||
// check if the program is already running
|
||||
if (!SingleInstance.IsFirstInstance)
|
||||
{
|
||||
SingleInstance.PassArgumentsToFirstInstance(args.Append(Constants.Parameter.Show));
|
||||
@@ -74,7 +79,7 @@ namespace Netch
|
||||
|
||||
SingleInstance.ArgumentsReceived.Subscribe(SingleInstance_ArgumentsReceived);
|
||||
|
||||
// 清理上一次的日志文件,防止淤积占用磁盘空间
|
||||
// clean up old logs
|
||||
if (Directory.Exists("logging"))
|
||||
{
|
||||
var directory = new DirectoryInfo("logging");
|
||||
@@ -90,14 +95,15 @@ namespace Netch
|
||||
|
||||
CreateLogger();
|
||||
|
||||
// 加载语言
|
||||
// load i18n
|
||||
i18N.Load(Global.Settings.Language);
|
||||
|
||||
// log environment information
|
||||
Task.Run(LogEnvironment).Forget();
|
||||
CheckClr();
|
||||
CheckOS();
|
||||
|
||||
// 绑定错误捕获
|
||||
// handle exceptions
|
||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
Application.ThreadException += Application_OnException;
|
||||
Application.ApplicationExit += Application_OnExit;
|
||||
@@ -108,6 +114,8 @@ namespace Netch
|
||||
Application.Run(Global.MainForm);
|
||||
}
|
||||
|
||||
#pragma warning restore VSTHRD002
|
||||
|
||||
private static void LogEnvironment()
|
||||
{
|
||||
Log.Information("Netch Version: {Version}", $"{UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
|
||||
@@ -167,6 +175,7 @@ namespace Netch
|
||||
|
||||
ConsoleHwnd = PInvoke.GetConsoleWindow();
|
||||
#if RELEASE
|
||||
// hide console window
|
||||
PInvoke.ShowWindow(ConsoleHwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
||||
#endif
|
||||
}
|
||||
@@ -202,7 +211,7 @@ namespace Netch
|
||||
{
|
||||
if (args.Contains(Constants.Parameter.Show))
|
||||
{
|
||||
Global.MainForm.ShowMainFormToolStripButton_Click(null!, null!);
|
||||
Utils.Utils.ActivateVisibleWindows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,5 +255,17 @@ namespace Netch.Utils
|
||||
var endIndex = str.IndexOf(':');
|
||||
return endIndex == -1 ? str : str[..endIndex];
|
||||
}
|
||||
|
||||
public static void ActivateVisibleWindows()
|
||||
{
|
||||
foreach (var f in Application.OpenForms.Cast<Form>())
|
||||
{
|
||||
if (!f.Visible)
|
||||
continue;
|
||||
|
||||
f.WindowState = FormWindowState.Normal;
|
||||
f.Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user