Skip to content

Commit 1d9135b

Browse files
committed
System tray icon
Add code for creation of system tray icon, menu and handle menu events
1 parent b26838f commit 1d9135b

File tree

6 files changed

+70
-4
lines changed

6 files changed

+70
-4
lines changed

src/App.Commands.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public static bool IsCheckForUpdateCommandVisible
3737
}
3838
}
3939

40-
public static readonly Command OpenPreferenceCommand = new Command(_ => OpenDialog(new Views.Preference()));
40+
public static readonly Command Unminimize = new Command(_ => ShowWindow());
41+
public static readonly Command OpenPreferenceCommand = new Command(_ => { ShowWindow(); OpenDialog(new Views.Preference()); });
4142
public static readonly Command OpenHotkeysCommand = new Command(_ => OpenDialog(new Views.Hotkeys()));
4243
public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir));
4344
public static readonly Command OpenAboutCommand = new Command(_ => OpenDialog(new Views.About()));

src/App.axaml.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
using Avalonia.Markup.Xaml;
1515
using Avalonia.Media;
1616
using Avalonia.Media.Fonts;
17+
using Avalonia.Media.Imaging;
18+
using Avalonia.Platform;
1719
using Avalonia.Platform.Storage;
1820
using Avalonia.Styling;
1921
using Avalonia.Threading;
@@ -167,6 +169,45 @@ public static void SetTheme(string theme, string themeOverridesFile)
167169
}
168170
}
169171

172+
public static void SetupTrayIcon(bool enable)
173+
{
174+
if (enable)
175+
{
176+
var icons = new TrayIcons {
177+
new TrayIcon {
178+
Icon = new WindowIcon(new Bitmap(AssetLoader.Open(new Uri("avares://SourceGit/App.ico")))),
179+
Menu = [
180+
new NativeMenuItem(Text("Open")) {Command = Unminimize},
181+
new NativeMenuItem(Text("Preference")) {Command = OpenPreferenceCommand},
182+
new NativeMenuItemSeparator(),
183+
new NativeMenuItem(Text("Quit")) {Command = QuitCommand},
184+
]
185+
}
186+
};
187+
icons[0].Clicked += (_, _) => ToggleWindow();
188+
TrayIcon.SetIcons(Current, icons);
189+
}
190+
}
191+
192+
private static void ToggleWindow() {
193+
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
194+
if (desktop.MainWindow.IsVisible) {
195+
desktop.MainWindow.Hide();
196+
} else {
197+
ShowWindow();
198+
}
199+
}
200+
}
201+
202+
private static void ShowWindow()
203+
{
204+
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
205+
desktop.MainWindow.WindowState = WindowState.Normal;
206+
desktop.MainWindow.Show();
207+
desktop.MainWindow.BringIntoView();
208+
desktop.MainWindow.Focus();
209+
}
210+
}
170211
public static void SetFonts(string defaultFont, string monospaceFont, bool onlyUseMonospaceFontInEditor)
171212
{
172213
var app = Current as App;
@@ -320,6 +361,7 @@ public override void OnFrameworkInitializationCompleted()
320361

321362
TryLaunchedAsNormal(desktop);
322363
}
364+
base.OnFrameworkInitializationCompleted();
323365
}
324366
#endregion
325367

@@ -476,11 +518,17 @@ private void TryLaunchedAsNormal(IClassicDesktopStyleApplicationLifetime desktop
476518
if (desktop.Args != null && desktop.Args.Length == 1 && Directory.Exists(desktop.Args[0]))
477519
startupRepo = desktop.Args[0];
478520

479-
_launcher = new ViewModels.Launcher(startupRepo);
521+
var pref = ViewModels.Preference.Instance;
522+
523+
SetupTrayIcon(pref.SystemTrayIcon);
524+
if (_createdSystemTrayIcon) {
525+
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
526+
}
527+
528+
_launcher = new ViewModels.Launcher(startupRepo) { InterceptQuit = _createdSystemTrayIcon };
480529
desktop.MainWindow = new Views.Launcher() { DataContext = _launcher };
481530

482531
#if !DISABLE_UPDATE_DETECTION
483-
var pref = ViewModels.Preference.Instance;
484532
if (pref.ShouldCheck4UpdateOnStartup())
485533
Check4Update();
486534
#endif

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@
420420
<x:String x:Key="Text.MoveRepositoryNode.Target" xml:space="preserve">Select parent node for:</x:String>
421421
<x:String x:Key="Text.Name" xml:space="preserve">Name:</x:String>
422422
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git has NOT been configured. Please to go [Preference] and configure it first.</x:String>
423+
<x:String x:Key="Text.Open" xml:space="preserve">Open SourceGit</x:String>
423424
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Open Data Storage Directory</x:String>
424425
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open with...</x:String>
425426
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>

src/ViewModels/Launcher.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public Workspace ActiveWorkspace
2929
private set => SetProperty(ref _activeWorkspace, value);
3030
}
3131

32+
public bool InterceptQuit { get; set; } = false;
33+
3234
public LauncherPage ActivePage
3335
{
3436
get => _activePage;

src/ViewModels/Preference.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ public double LastCheckUpdateTime
348348
set => SetProperty(ref _lastCheckUpdateTime, value);
349349
}
350350

351+
public bool SystemTrayIcon
352+
{
353+
get => _systemTrayIcon;
354+
set => SetProperty(ref _systemTrayIcon, value);
355+
}
356+
351357
public bool IsGitConfigured()
352358
{
353359
var path = GitInstallPath;
@@ -682,5 +688,7 @@ private string FixFontFamilyName(string name)
682688
private string _externalMergeToolPath = string.Empty;
683689

684690
private uint _statisticsSampleColor = 0xFF00FF00;
691+
692+
private bool _systemTrayIcon = false;
685693
}
686694
}

src/Views/Launcher.axaml.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,13 @@ protected override void OnKeyUp(KeyEventArgs e)
255255

256256
protected override void OnClosing(WindowClosingEventArgs e)
257257
{
258-
(DataContext as ViewModels.Launcher)?.Quit(Width, Height);
258+
var launcher = DataContext as ViewModels.Launcher;
259+
if (launcher is { InterceptQuit: true }) {
260+
e.Cancel = true;
261+
Hide();
262+
} else {
263+
launcher?.Quit(Width, Height);
264+
}
259265
base.OnClosing(e);
260266
}
261267

0 commit comments

Comments
 (0)