-
-
Notifications
You must be signed in to change notification settings - Fork 739
Closed
Description
In my case it is related to the application localization, but it could be also useful for some other scenarios (like change item visibility or enable/disable item).
Currently I have this Desktoper class to bring the app to the desktop.
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using ElectronNET.API;
using ElectronNET.API.Entities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Tum4ik.RemoteControl.Server.Services;
using Tum4ik.RemoteControl.Server.Services.MQTT.MqttServer;
namespace Tum4ik.RemoteControl.Server.Desktop
{
/// <inheritdoc />
public class Desktoper : IDesktoper
{
private const string TrayRunIcon = "Desktop/icons/tray-run-icon.png";
private const string TrayStopIcon = "Desktop/icons/tray-stop-icon.png";
private readonly IServiceProvider _serviceProvider;
private readonly IHostingEnvironment _env;
private readonly IStringLocalizer<Desktoper> _localizer;
private readonly IMqttServerService _mqttServerService;
private BrowserWindow _settingsWindow;
private readonly MenuItem[] _menuItems;
public Desktoper(IServiceProvider serviceProvider,
IHostingEnvironment env,
IStringLocalizer<Desktoper> localizer,
IMqttServerService mqttServerService)
{
_serviceProvider = serviceProvider;
_env = env;
_localizer = localizer;
_mqttServerService = mqttServerService;
_menuItems = CreateMenuItems();
}
private MenuItem _runServerMenuItem;
private MenuItem _stopServerMenuItem;
private MenuItem _settingsMenuItem;
private MenuItem _aboutMenuItem;
private MenuItem _exitMenuItem;
private readonly Func<IStringLocalizer, string> _runServerMenuItemLabelFunc = localizer => localizer["Run Server"];
private readonly Func<IStringLocalizer, string> _stopServerMenuItemLabelFunc = localizer => localizer["Stop Server"];
private readonly Func<IStringLocalizer, string> _settingsMenuItemLabelFunc = localizer => localizer["Settings"];
private readonly Func<IStringLocalizer, string> _aboutMenuItemLabelFunc = localizer => localizer["About"];
private readonly Func<IStringLocalizer, string> _exitMenuItemLabelFunc = localizer => localizer["Exit"];
private MenuItem[] CreateMenuItems()
{
var trayMenuRunIcon = Path.Combine(_env.ContentRootPath, "Desktop/icons/tray-menu-run-icon.png");
var trayMenuStopIcon = Path.Combine(_env.ContentRootPath, "Desktop/icons/tray-menu-stop-icon.png");
var trayMenuSettingIcon = Path.Combine(_env.ContentRootPath, "Desktop/icons/tray-menu-settings-icon.png");
var trayMenuAboutIcon = Path.Combine(_env.ContentRootPath, "Desktop/icons/tray-menu-about-icon.png");
var trayMenuExitIcon = Path.Combine(_env.ContentRootPath, "Desktop/icons/tray-menu-exit-icon.png");
var settingsWindowOptions = new BrowserWindowOptions
{
MinWidth = 800,
MinHeight = 400,
Width = 800,
Height = 400,
Frame = false,
Icon = trayMenuSettingIcon,
// BackgroundColor = "#FF080F17",
Fullscreenable = false,
Center = true
};
_runServerMenuItem = new MenuItem
{
Label = _runServerMenuItemLabelFunc(_localizer),
Icon = trayMenuRunIcon
};
_stopServerMenuItem = new MenuItem
{
Label = _stopServerMenuItemLabelFunc(_localizer),
Icon = trayMenuStopIcon,
Visible = false,
Enabled = false
};
_runServerMenuItem.Click = async () =>
{
await _mqttServerService.StartAsync();
_stopServerMenuItem.Visible = true;
_stopServerMenuItem.Enabled = true;
_runServerMenuItem.Visible = false;
_runServerMenuItem.Enabled = false;
Electron.Tray.SetImage(Path.Combine(_env.ContentRootPath, TrayRunIcon));
};
_stopServerMenuItem.Click = async () =>
{
await _mqttServerService.StopAsync();
_runServerMenuItem.Visible = true;
_runServerMenuItem.Enabled = true;
_stopServerMenuItem.Visible = false;
_stopServerMenuItem.Enabled = false;
Electron.Tray.SetImage(Path.Combine(_env.ContentRootPath, TrayStopIcon));
};
_settingsMenuItem = new MenuItem
{
Label = _settingsMenuItemLabelFunc(_localizer),
Icon = trayMenuSettingIcon,
Click = async () =>
{
_settingsWindow = await Electron.WindowManager.CreateWindowAsync(settingsWindowOptions);
_settingsWindow.Center();
}
};
_aboutMenuItem = new MenuItem
{
Label = _aboutMenuItemLabelFunc(_localizer),
Icon = trayMenuAboutIcon
};
_exitMenuItem = new MenuItem
{
Label = _exitMenuItemLabelFunc(_localizer),
Icon = trayMenuExitIcon,
Click = () => Electron.App.Quit()
};
var menuItems = new[]
{
_runServerMenuItem,
_stopServerMenuItem,
_settingsMenuItem,
_aboutMenuItem,
new MenuItem
{
Type = MenuType.separator
},
_exitMenuItem
};
return menuItems;
}
public void Desktopize()
{
var culture = GetCultureFromDb();
UpdateMenuItems(culture);
Electron.WindowManager.IsQuitOnWindowAllClosed = false;
Electron.Tray.Show(TrayStopIcon, _menuItems);
}
public void CloseSettingsWindow()
{
_settingsWindow?.Close();
}
public void UpdateCulture(string culture)
{
UpdateMenuItems(culture);
Electron.Tray.Destroy();
Electron.Tray.Show(TrayStopIcon, _menuItems);
}
private void UpdateMenuItems(string culture)
{
var cultureInfo = new CultureInfo(culture);
var localizer = _localizer.WithCulture(cultureInfo);
_runServerMenuItem.Label = _runServerMenuItemLabelFunc(localizer);
_stopServerMenuItem.Label = _stopServerMenuItemLabelFunc(localizer);
_settingsMenuItem.Label = _settingsMenuItemLabelFunc(localizer);
_aboutMenuItem.Label = _aboutMenuItemLabelFunc(localizer);
_exitMenuItem.Label = _exitMenuItemLabelFunc(localizer);
}
private string GetCultureFromDb()
{
var database = _serviceProvider.CreateScope().ServiceProvider.GetService<DatabaseService>();
var settings = database.Settings.FirstOrDefault();
return settings?.Language ?? "en-US";
}
}
}
The Desktopize
method is called from Startup Configure
method.
The public UpdateCulture
method is called from the settings controller when the culture is changed.
So I do this trick: destroy tray and then create it again with updated menu items. I guess it will be very useful to have such functionality, for example
Electron.Tray.UpdateMenuItem("menu_item_id", menuItem =>
{
menuItem.Label = "changed_label",
Enabled = false,
Click = () => SomeNewBehavior()
});
Thanks!