Tray notification icon dot

This commit is contained in:
Natsumi
2025-10-30 01:16:17 +11:00
parent 814a66abea
commit 3836b9b4ce
15 changed files with 90 additions and 35 deletions
+5
View File
@@ -216,5 +216,10 @@ namespace VRCX
using var client = MainForm.Instance.Browser.GetDevToolsClient(); using var client = MainForm.Instance.Browser.GetDevToolsClient();
_ = client.Network.SetUserAgentOverrideAsync(Program.Version); _ = client.Network.SetUserAgentOverrideAsync(Program.Version);
} }
public override void SetTrayIconNotification(bool notify)
{
MainForm.Instance.BeginInvoke(new MethodInvoker(() => { MainForm.Instance.SetTrayIconNotification(notify); }));
}
} }
} }
+1
View File
@@ -14,6 +14,7 @@ namespace VRCX
public abstract void SetZoom(double zoomLevel); public abstract void SetZoom(double zoomLevel);
public abstract Task<double> GetZoom(); public abstract Task<double> GetZoom();
public abstract void DesktopNotification(string BoldText, string Text = "", string Image = ""); public abstract void DesktopNotification(string BoldText, string Text = "", string Image = "");
public abstract void SetTrayIconNotification(bool notify);
public abstract void RestartApplication(bool isUpgrade); public abstract void RestartApplication(bool isUpgrade);
public abstract bool CheckForUpdateExe(); public abstract bool CheckForUpdateExe();
+4
View File
@@ -143,5 +143,9 @@ namespace VRCX
public override void SetUserAgent() public override void SetUserAgent()
{ {
} }
public override void SetTrayIconNotification(bool notify)
{
}
} }
} }
+13 -5
View File
@@ -7,7 +7,7 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Drawing; using System.Drawing;
using System.Reflection; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using CefSharp; using CefSharp;
using CefSharp.WinForms; using CefSharp.WinForms;
@@ -22,6 +22,8 @@ namespace VRCX
public static NativeWindow nativeWindow; public static NativeWindow nativeWindow;
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public ChromiumWebBrowser Browser; public ChromiumWebBrowser Browser;
private readonly Icon _appIcon;
private readonly Icon _appIconNoty;
private readonly Timer _saveTimer; private readonly Timer _saveTimer;
private int LastLocationX; private int LastLocationX;
private int LastLocationY; private int LastLocationY;
@@ -41,10 +43,11 @@ namespace VRCX
_saveTimer.Tick += SaveTimer_Tick; _saveTimer.Tick += SaveTimer_Tick;
try try
{ {
var location = Assembly.GetExecutingAssembly().Location; var path = Path.GetDirectoryName(Environment.ProcessPath) ?? string.Empty;
var icon = Icon.ExtractAssociatedIcon(location); _appIcon = new Icon(Path.Combine(path, "VRCX.ico"));
Icon = icon; _appIconNoty = new Icon(Path.Combine(path, "VRCX_notify.ico"));
TrayIcon.Icon = icon; Icon = _appIcon;
TrayIcon.Icon = _appIcon;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -246,5 +249,10 @@ namespace VRCX
SaveWindowState(); SaveWindowState();
Application.Exit(); Application.Exit();
} }
public void SetTrayIconNotification(bool notify)
{
TrayIcon.Icon = notify ? _appIconNoty : _appIcon;
}
} }
} }
+4 -1
View File
@@ -85,6 +85,9 @@
<Content Include="..\images\VRCX.ico"> <Content Include="..\images\VRCX.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="..\images\VRCX_notify.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\images\VRCX.png"> <Content Include="..\images\VRCX.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -100,7 +103,7 @@
<PackageReference Include="Silk.NET.Direct3D11" Version="2.22.0" /> <PackageReference Include="Silk.NET.Direct3D11" Version="2.22.0" />
<PackageReference Include="Silk.NET.DXGI" Version="2.22.0" /> <PackageReference Include="Silk.NET.DXGI" Version="2.22.0" />
<PackageReference Include="Silk.NET.Windowing" Version="2.22.0" /> <PackageReference Include="Silk.NET.Windowing" Version="2.22.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" /> <PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" />
<PackageReference Include="System.Data.SQLite" Version="2.0.2" /> <PackageReference Include="System.Data.SQLite" Version="2.0.2" />
+4 -1
View File
@@ -64,6 +64,9 @@
<Content Include="..\images\VRCX.ico"> <Content Include="..\images\VRCX.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="..\images\VRCX_notify.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\images\VRCX.png"> <Content Include="..\images\VRCX.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -74,7 +77,7 @@
<PackageReference Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageReference Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="NLog" Version="6.0.5" /> <PackageReference Include="NLog" Version="6.0.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" /> <PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" />
<PackageReference Include="System.Data.SQLite" Version="2.0.2" /> <PackageReference Include="System.Data.SQLite" Version="2.0.2" />
+4 -1
View File
@@ -69,6 +69,9 @@
<Content Include="..\images\VRCX.ico"> <Content Include="..\images\VRCX.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="..\images\VRCX_notify.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\images\VRCX.png"> <Content Include="..\images\VRCX.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -79,7 +82,7 @@
<PackageReference Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageReference Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="NLog" Version="6.0.5" /> <PackageReference Include="NLog" Version="6.0.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" /> <PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" />
<PackageReference Include="System.Data.SQLite" Version="1.0.119" /> <PackageReference Include="System.Data.SQLite" Version="1.0.119" />
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+2
View File
@@ -83,6 +83,8 @@
"src-electron/*", "src-electron/*",
"images/VRCX.png", "images/VRCX.png",
"images/VRCX.ico", "images/VRCX.ico",
"images/VRCX_notify.png",
"images/VRCX_notify.ico",
"Version", "Version",
"src-electron/libs/linux/libopenvr_api.so" "src-electron/libs/linux/libopenvr_api.so"
], ],
+30 -26
View File
@@ -161,28 +161,6 @@ if (!gotTheLock) {
}); });
} }
ipcMain.handle('getArch', () => {
return process.arch.toString();
});
ipcMain.handle('applyWindowSettings', (event, position, size, state) => {
if (position) {
mainWindow.setPosition(parseInt(position.x), parseInt(position.y));
}
if (size) {
mainWindow.setSize(parseInt(size.width), parseInt(size.height));
}
if (state) {
if (state === '0') {
mainWindow.restore();
} else if (state === '1') {
mainWindow.restore();
} else if (state === '2') {
mainWindow.maximize();
}
}
});
ipcMain.handle('dialog:openFile', async () => { ipcMain.handle('dialog:openFile', async () => {
const result = await dialog.showOpenDialog(mainWindow, { const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'], properties: ['openFile'],
@@ -278,6 +256,14 @@ ipcMain.handle(
} }
); );
ipcMain.handle('app:getArch', () => {
return process.arch.toString();
});
ipcMain.handle('app:setTrayIconNotification', (event, notify) => {
setTrayIconNotification(notify);
});
function tryRelaunchWithArgs(args) { function tryRelaunchWithArgs(args) {
if ( if (
process.platform !== 'linux' || process.platform !== 'linux' ||
@@ -536,21 +522,35 @@ function destroyHmdOverlayWindow() {
hmdOverlayWindow = undefined; hmdOverlayWindow = undefined;
} }
let tray = null;
let trayIcon = null;
let trayIconNotify = null;
function createTray() { function createTray() {
let tray = null;
if (process.platform === 'darwin') { if (process.platform === 'darwin') {
const image = nativeImage.createFromPath( const image = nativeImage.createFromPath(
path.join(rootDir, 'images/VRCX.png') path.join(rootDir, 'images/VRCX.png')
); );
tray = new Tray(image.resize({ width: 16, height: 16 })); trayIcon = image.resize({ width: 16, height: 16 });
const imageNotify = nativeImage.createFromPath(
path.join(rootDir, 'images/VRCX_notify.png')
);
trayIconNotify = imageNotify.resize({ width: 16, height: 16 });
} else if (process.platform === 'linux') { } else if (process.platform === 'linux') {
const image = nativeImage.createFromPath( const image = nativeImage.createFromPath(
path.join(rootDir, 'images/VRCX.png') path.join(rootDir, 'images/VRCX.png')
); );
tray = new Tray(image.resize({ width: 64, height: 64 })); trayIcon = image.resize({ width: 64, height: 64 });
const imageNotify = nativeImage.createFromPath(
path.join(rootDir, 'images/VRCX_notify.png')
);
trayIconNotify = imageNotify.resize({ width: 64, height: 64 });
} else { } else {
tray = new Tray(path.join(rootDir, 'images/VRCX.ico')); trayIcon = path.join(rootDir, 'images/VRCX.ico');
trayIconNotify = path.join(rootDir, 'images/VRCX_notify.ico');
} }
tray = new Tray(trayIcon);
const contextMenu = Menu.buildFromTemplate([ const contextMenu = Menu.buildFromTemplate([
{ {
label: 'Open', label: 'Open',
@@ -583,6 +583,10 @@ function createTray() {
}); });
} }
function setTrayIconNotification(notify) {
tray.setImage(notify ? trayIconNotify : trayIcon);
}
async function installVRCX() { async function installVRCX() {
console.log('Home path:', homePath); console.log('Home path:', homePath);
console.log('AppImage path:', appImagePath); console.log('AppImage path:', appImagePath);
+3 -1
View File
@@ -22,7 +22,9 @@ contextBridge.exposeInMainWorld('interopApi', {
const validChannels = ['launch-command']; const validChannels = ['launch-command'];
contextBridge.exposeInMainWorld('electron', { contextBridge.exposeInMainWorld('electron', {
getArch: () => ipcRenderer.invoke('getArch'), getArch: () => ipcRenderer.invoke('app:getArch'),
setTrayIconNotification: (notify) =>
ipcRenderer.invoke('app:setTrayIconNotification', notify),
openFileDialog: () => ipcRenderer.invoke('dialog:openFile'), openFileDialog: () => ipcRenderer.invoke('dialog:openFile'),
openDirectoryDialog: () => ipcRenderer.invoke('dialog:openDirectory'), openDirectoryDialog: () => ipcRenderer.invoke('dialog:openDirectory'),
onWindowPositionChanged: (callback) => onWindowPositionChanged: (callback) =>
+18
View File
@@ -23,6 +23,7 @@ export const useUiStore = defineStore('Ui', () => {
const notifiedMenus = ref([]); const notifiedMenus = ref([]);
const shiftHeld = ref(false); const shiftHeld = ref(false);
const trayIconNotify = ref(false);
watch( watch(
() => watchState.isLoggedIn, () => watchState.isLoggedIn,
@@ -41,6 +42,7 @@ export const useUiStore = defineStore('Ui', () => {
!notifiedMenus.value.includes(index) !notifiedMenus.value.includes(index)
) { ) {
notifiedMenus.value.push(index); notifiedMenus.value.push(index);
updateTrayIconNotify();
} }
} }
@@ -58,6 +60,22 @@ export const useUiStore = defineStore('Ui', () => {
function removeNotify(index) { function removeNotify(index) {
notifiedMenus.value = notifiedMenus.value.filter((i) => i !== index); notifiedMenus.value = notifiedMenus.value.filter((i) => i !== index);
updateTrayIconNotify();
}
function updateTrayIconNotify() {
const newState =
notifiedMenus.value.includes('notification') ||
notifiedMenus.value.includes('friendLog');
if (trayIconNotify.value !== newState) {
trayIconNotify.value = newState;
if (LINUX) {
window.electron.setTrayIconNotification(trayIconNotify.value);
return;
}
AppApi.SetTrayIconNotification(trayIconNotify.value);
}
} }
return { return {
+2
View File
@@ -36,6 +36,7 @@ declare global {
}; };
electron: { electron: {
getArch: () => Promise<string>; getArch: () => Promise<string>;
setTrayIconNotification: (notify: boolean) => Promise<void>;
openFileDialog: () => Promise<string>; openFileDialog: () => Promise<string>;
openDirectoryDialog: () => Promise<string>; openDirectoryDialog: () => Promise<string>;
desktopNotification: ( desktopNotification: (
@@ -187,6 +188,7 @@ declare global {
CopyImageToClipboard(path: string): Promise<void>; CopyImageToClipboard(path: string): Promise<void>;
FlashWindow(): Promise<void>; FlashWindow(): Promise<void>;
SetUserAgent(): Promise<void>; SetUserAgent(): Promise<void>;
SetTrayIconNotification(notify: boolean): Promise<void>;
// Common Functions // Common Functions
GetColourFromUserID(userId: string): Promise<number>; GetColourFromUserID(userId: string): Promise<number>;