010 ΠœΠΎΠ΄ΡƒΠ»ΡŒ app

ΠœΠΎΠ΄ΡƒΠ»ΡŒ app это ΡƒΠΆΠ΅ Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ со своими ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒΡΡ

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° on элСктрон подписываСт основной процСсс Π½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹Π΅ события

src > main > index.js

import { app } from "electron";
 
// это ΠΈΠ²Π΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ срабатываСт Π½Π° macOS ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ прилоТСния
app.on("will-finish-launching", () => {
	console.log("will-finish-launching");
});
 
// Π­Ρ‚ΠΎ ΠΈΠ²Π΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ срабатываСт ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ прилоТСния
app.on("ready", () => {
	console.log("ready");
});

Π’Π°ΠΊ ΠΆΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π²ΠΏΠΎΠ»Π½Π΅ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ промисом, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

import { app } from "electron";
app.whenReady().then(() => console.log("App is ready"));

Π’Π°ΠΊ ΠΆΠ΅ Ρƒ нас Π΅ΡΡ‚ΡŒ ΠΈΠ²Π΅Π½Ρ‚Ρ‹ Π½Π° Π²Ρ‹Ρ…ΠΎΠ΄:

  • before-quit Π΄ΠΎ закрытия всСх ΠΎΠΊΠΎΠ½ прилоТСния
  • will-quit послС закрытия всСх ΠΎΠΊΠΎΠ½ прилоТСния
  • quit срабатываниС ΠΏΡ€ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π΅ ΠΈΠ· прилоТСния

ΠžΡ‚ смСны порядка ΠΈΡ… Π²Ρ‹Ρ…ΠΎΠ΄Π° Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ помСняСтся - ΠΎΠ½ΠΈ всСгда ΠΈΠΌΠ΅ΡŽΡ‚ своё собствСнноС врСмя Π²Ρ‹Π·ΠΎΠ²Π°

import { app } from "electron";
 
app.on("before-quit", () => console.log("before quit"));
app.on("will-quit", () => console.log("will quit"));
app.on("quit", () => console.log("quit"));
 
app.whenReady().then(() => {
	// функция quit Π²Ρ‹ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
	setTimeout(() => app.quit(), 3000);
});

Π’Π°ΠΊ ΠΆΠ΅ ΠΌΡ‹ ΠΈΠΌΠ΅Π΅ΠΌ Π΄Π²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Π²Ρ‹Ρ…ΠΎΠ΄Π° ΠΈΠ· прилоТСния:

  • quit() - выполняСт ΠΈΠ²Π΅Π½Ρ‚Ρ‹ quit. ΠžΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ Π²Ρ‹Ρ…ΠΎΠ΄.
  • exit() - Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚, выполняя Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ²Π΅Π½Ρ‚ quit ΠΈ Π±Π΅Π· ΡΠΏΡ€Π°ΡˆΠΈΠ²Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Π’Ρ‹Ρ…ΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ стоит ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ ошибкС

ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ getAppPath() (ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹) ΠΈ getPath() (ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ любой ΠΏΡƒΡ‚ΡŒ) ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ ΠΏΡƒΡ‚ΠΈ Π½Π° ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π΅.

ΠšΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎ Ρ‚ΡƒΡ‚ ΠΏΡ€ΠΈ запускС Π΄Π΅Π±Π°Π³Π³Π΅Ρ€Π° ΠΌΡ‹ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Ρ‚Ρ‹ΠΊΠ°Π΅ΠΌ ΠΏΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡŽ ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ ΠΊ Ρ‚ΠΎΡ‡ΠΊΠ΅ останова Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π°, Π³Π΄Π΅ ΠΌΡ‹ сгСнСрировали ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ application.

import { app } from "electron";
 
app.whenReady().then(() => {
	let application = app;
	debugger;
});

А Ρ‚ΡƒΡ‚ ΡƒΠΆΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ прилоТСния

Π”Π°Π»ΡŒΡˆΠ΅ ΠΈΠ΄Ρ‘Ρ‚ функция getPath(), Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π²Π°ΠΆΠ½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ:

  • temp - Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅
  • userData - всС Π΄Π°Π½Π½Ρ‹Π΅ связанныС с ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ
  • logs - ΠΏΠ°ΠΏΠΊΠ° с Π»ΠΎΠ³Π°ΠΌΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹
  • exe - ΠΏΠ°ΠΏΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

ВсС ΠΈΠΌΠ΅Π½Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²Π»ΠΎΠΆΠΈΡ‚ΡŒ Π² getPath()

  • nameΒ string - You can request the following paths by the name:
  • homeΒ User’s home directory.
  • appDataΒ Per-user application data directory, which by default points to:
  • %APPDATA%Β on Windows
  • $XDG_CONFIG_HOMEΒ orΒ ~/.configΒ on Linux
  • ~/Library/Application SupportΒ on macOS
  • userDataΒ The directory for storing your app’s configuration files, which by default is theΒ appDataΒ directory appended with your app’s name. By convention files storing user data should be written to this directory, and it is not recommended to write large files here because some environments may backup this directory to cloud storage.
  • sessionDataΒ The directory for storing data generated byΒ Session, such as localStorage, cookies, disk cache, downloaded dictionaries, network state, devtools files. By default this points toΒ userData. Chromium may write very large disk cache here, so if your app does not rely on browser storage like localStorage or cookies to save user data, it is recommended to set this directory to other locations to avoid polluting theΒ userDataΒ directory.
  • tempΒ Temporary directory.
  • exeΒ The current executable file.
  • moduleΒ TheΒ libchromiumcontentΒ library.
  • desktopΒ The current user’s Desktop directory.
  • documentsΒ Directory for a user’s β€œMy Documents”.
  • downloadsΒ Directory for a user’s downloads.
  • musicΒ Directory for a user’s music.
  • picturesΒ Directory for a user’s pictures.
  • videosΒ Directory for a user’s videos.
  • recentΒ Directory for the user’s recent files (Windows only).
  • logsΒ Directory for your app’s log folder.
  • crashDumpsΒ Directory where crash dumps are stored.

Π’Π°ΠΊ ΠΆΠ΅ Ρƒ нас ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹ΠΉ экзСмпляр app. Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ссли Π±Ρ‹ Ρƒ нас Π±Ρ‹Π»ΠΎ нСсколько Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹Ρ… основных процСссов, Ρ‚ΠΎ всС Π±Ρ‹ ΠΎΠ½ΠΈ отправляли запросы Π½Π° ΠΎΠ΄ΠΈΠ½ API ΠΈ это Π²Ρ‹Π·Π²Π°Π»ΠΎ Π±Ρ‹ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Ρ‹.

Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ Π΄Π°Π»ΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ нСсколько ΠΎΠΊΠΎΠ½ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ вмСсто запуска ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ прилоТСния нСсколько Ρ€Π°Π·

Однако Π½ΡƒΠΆΠ½ΠΎ ΡƒΠΏΠΎΠΌΡΠ½ΡƒΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ экзСмпляр ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Ρ‡Π΅Ρ€Π΅Π· консоль, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ нСприятным послСдствиям. Для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ:

// ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ экзСмпляр Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π΄Π°Π½Π½ΠΎΠ³ΠΎ прилоТСния
const lock = app.releaseSingleInstanceLock();
 
// Ссли ΠΌΡ‹ Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΏΡƒΡ‰Π΅Π½ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, поэтому
if (!lock) {
	// Π²Ρ‹Ρ…ΠΎΠ΄ ΠΈΠ· прилоТСния
	app.quit();
} else {
	// Ссли пытаСмся ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ инстанс, Ρ‚ΠΎ
	app.on("second-instance", () => {
		// создаёт фокус Π½Π° Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ
		app.focus();
		// Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ Π»ΠΎΠ³ ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ запуска Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°
		console.log("App is alredy running");
	})
}

блокировказапускавторогоэкзСмпляраприлоТСния ΠžΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΠΌΠ΅Π½Π½ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½, прСдставлСнный Π½ΠΈΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ:

import { app, BrowserWindow } from "electron";
 
let myWindow = null;
 
const gotTheLock = app.requestSingleInstanceLock();
 
if (!gotTheLock) {
	app.quit();
} else {
	app.on("second-instance", (event, commandLine, workingDirectory) => {
		// ΠΊΠΎΠ³Π΄Π° ΠΊΡ‚ΠΎ-Ρ‚ΠΎ пытаСтся Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ экзСмпляр прилоТСния, Π½ΡƒΠΆΠ½ΠΎ ΡΡ„ΠΎΠΊΡƒΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΌ
		if (myWindow) {
			if (myWindow.isMinimized()) myWindow.restore();
			myWindow.focus();
		}
	});
	// создаём myWindow ΠΈ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
	app.on("ready", () => {
		let window = new BrowserWindow({
			width: 1280,
			height: 720,
		});
 
		window.loadURL("https://google.com");
	});
}
 

Ѐункция showAboutPanel() ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ панСль ΠΎ нашСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅. Однако Π±Π΅Π· инстанса нашСго ΠΎΠΊΠ½Π°, Ρƒ нас Π²Ρ‹ΠΉΠ΄Π΅Ρ‚ ΠΎΠΊΠ½ΠΎ ΠΎ вСрсии элСктрона

import { app } from "electron";
 
const lock = app.releaseSingleInstanceLock();
 
if (!lock) {
	app.quit();
} else {
	app.on("second-instance", () => {
		if (win) {
			win.focus();
		}
	})
}
 
app.whenReady().then(() => {
	// ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ панСль ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅
	app.showAboutPanel();
});
 

011 ΠœΠΎΠ΄ΡƒΠ»ΡŒ BrowserWindow

ΠœΠΎΠ΄ΡƒΠ»ΡŒ BrowserWindow Ρ…Ρ€Π°Π½ΠΈΡ‚ Π² сСбС класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт Π½Π°ΠΌ конструктор Π½ΠΎΠ²ΠΎΠ³ΠΎ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π½ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π°, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ позволяСт Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ

import { app, BrowserWindow } from "electron";
 
app.on("ready", () => {
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
	});
 
	// Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ страницу ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚-рСсурса
	window.loadURL("https://google.com");
});

Π£ΠΆΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ loadFile() Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΡ‚ структуру страницы ΠΈΠ· Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ Π½Π°ΠΌ Ρ„Π°ΠΉΠ»Π°

app.on("ready", () => {
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
	});
 
	// этот ΠΌΠ΅Ρ‚ΠΎΠ΄ позволяСт Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΡ‚ΡŒ Π² ΠΎΠΊΠ½Π΅ наши страницы
	window.loadFile("renderer/index.html");
});

Π’Π°ΠΊ ΠΆΠ΅, Π² процСссС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ нашСго прилоТСния, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒΡΡ с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρƒ нас ΠΌΠΎΠ³ΡƒΡ‚ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Π΅Ρ‰ΠΈ (ΠΏΠΎ Ρ‚ΠΈΠΏΡƒ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΎΠ²) Π½Π° Ρ„Ρ€ΠΎΠ½Ρ‚Π΅ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°. Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ свойством Π²Π΅Π±-настройки nodeIntegration, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставит Ρ€Π°Π±ΠΎΡ‚Ρƒ с ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΈ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€ΠΎΠΌ ΠΈΠ· devtools. Π­Ρ‚ΠΎ нСбСзопасная опция, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π½Π΅ стоит ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ, Π½ΠΎ Π²ΠΎ врСмя Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ. Π—Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ эту настройку ΠΌΠΎΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ вдальнСйшСм ΠΏΡ€Π΅Π»ΠΎΠ°Π΄ΠΎΠΌ

app.on("ready", () => {
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		// ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π΅Π½Π΄Π΅Ρ€Π΅Ρ€-процСссу доступ ΠΊ node API
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
	window.webContents.openDevTools();
});

Π”Π°Π»Π΅Π΅ ΠΌΡ‹ Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΠ·Π±Π°Π²ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ Ρ„Π»ΠΈΠΊΠ΅Ρ€-эффСкта (эффСкт, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Ρƒ нас сначала рСндСрится сама HTML-структура, Π° ΡƒΠΆΠ΅ Π·Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠΆΠ°ΡŽΡ‚ΡΡ стили). Для этого ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΈΠ²Π΅Π½Ρ‚, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΎΠΊΠ½ΠΎ покаТСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ Ρ€Π΅Π½Π΄Π΅Ρ€Π° страницы ΠΈ Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ Ρ†Π²Π΅Ρ‚ для нашСго ΠΎΠΊΠ½Π° Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ (Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π½Π° Π±Π΅Π»ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ)

app.on("ready", () => {
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		// Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ ΠΎΠΊΠ½ΠΎ сразу
		show: false,
		// Ρ„ΠΎΠ½ ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π²Π΅Π½ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ находится Π² стилях
		backgroundColor: "#2c3e50",
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	// подписываСмся Π½Π° событиС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ сработаСт, ΠΊΠΎΠ³Π΄Π° ΠΎΠΊΠ½ΠΎ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ загрузится
	window.on("ready-to-show", () => {
		// ... Π½ΡƒΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ Π΅Π³ΠΎ
		window.show();
	});
 
	window.webContents.openDevTools();
});

Π’Π°ΠΊ ΠΆΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ нашСго ΠΎΠΊΠ½Π° Ρ‡Π΅Ρ€Π΅Π· ΠΌΠΎΠ΄ΡƒΠ»ΡŒ screen, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ…Ρ€Π°Π½ΠΈΡ‚ Π² сСбС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΈ свойства Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ ΠΎΠΊΠ½Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ

import { app, screen, BrowserWindow } from "electron";
 
app.on("ready", () => {
	// Ρ‚ΡƒΡ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠΊΠ½Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ
	const { width, height } = screen.getPrimaryDisplay().workAreaSize;
	console.log(`${width} - ${height}`);
 
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		// Ρ‚ΡƒΡ‚ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρ‹ ΠΎΠΊΠ½Π°
		minHeight: 500,
		minWidth: 500,
		// Ρ‚ΡƒΡ‚ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρ‹ ΠΎΠΊΠ½Π°
		maxHeight: height < 1080 ? 1080 : height,
		maxWidth: width,
		show: false,
		backgroundColor: "#2c3e50",
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	window.on("ready-to-show", () => {
		window.show();
	});
 
	window.webContents.openDevTools();
});
 

Π”Π°Π»ΡŒΡˆΠ΅ ΡƒΠΆΠ΅ ΠΈΠ΄ΡƒΡ‚ свойства Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΎΠΊΠ½ΠΎΠΌ прилоТСния

  • frame: false - скроСт Ρ€Π°ΠΌΠΊΡƒ Ρƒ прилоТСния Π²ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅
  • titleBarStyle: "hidden" - ΠΈΠΌΠ΅Π΅Ρ‚ нСсколько свойств (ΠΏΠΎΡ‡Ρ‚ΠΈ всС для ΠΌΠ°ΠΊΠ°), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ элСмСнтов ΠΊΠ½ΠΎΠΏΠΎΠΊ ΠΈ самой Ρ€Π°ΠΌΠΊΠΈ

И Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΡƒΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ Π΄Ρ€Π°Π³-ΠΎΠ±Π»Π°ΡΡ‚ΡŒ, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ смоТСм ΠΏΠ΅Ρ€Π΅Ρ‚Π°ΡΠΊΠΈΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Ρƒ нас сСйчас Π½Π΅Ρ‚ Π²Π΅Ρ€Ρ…Π°

<div class="title-bar"></div>
.title-bar {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 30px;
	background: #3498db;
 
	// эта настройка надСляСт элСмСнт с Π΄Π°Π½Π½Ρ‹ΠΌ классом ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ пСрСтаскивания
	-webkit-app-region: drag;
}

012 ΠœΠΎΠ΄ΡƒΠ»ΡŒ Menu

Π‘Ρ€Π°Π·Ρƒ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π»ΠΈΠ±ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ стоковоС мСню, Π»ΠΈΠ±ΠΎ создаём своё мСню ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ с нуля.

Π­Ρ‚ΠΎ самый ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ способ создания мСню прилоТСния (самый Π΄ΠΎΠ»Π³ΠΈΠΉ ΠΈ Π΄Π»ΠΈΠ½Π½Ρ‹ΠΉ с ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°):

import { app, screen, BrowserWindow, Menu, MenuItem } from "electron";
 
app.on("ready", () => {
	// создаём наш собствСнный инстанс мСню
	const menu = new Menu();
 
	// Ρ‚ΡƒΡ‚ ΡƒΠΆΠ΅ добавляСм ΠΏΡƒΠ½ΠΊΡ‚Ρ‹ мСню Π² нашС мСню
	menu.append(
		// ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π·Π΄Π΅Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΆΠ΅ создаётся Ρ‡Π΅Ρ€Π΅Π· инстанс ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° мСню
		new MenuItem({
			// Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ€Π°Π·Π΄Π΅Π»Π°
			label: "MyApp",
			// опрСдСляСм массив подмСню
			submenu: [
				// ΠΏΠ΅Ρ€Π²ΠΎΠ΅ подмСню
				new MenuItem({
					// имя подмСню
					label: "Option 1",
					// Π»ΠΎΠ³ΠΈΠΊΠ° ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ
					click() {
						console.log("Option 1 clicked");
					},
				}),
				// Ρ‚Π°ΠΊ ΠΆΠ΅ Ρ‡Π΅Ρ€Π΅Π· ΠΌΠ΅Π½ΡŽΠΠΉΡ‚Π΅ΠΌ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²
				new MenuItem({
					// это Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ ΠΏΡƒΠ½ΠΊΡ‚ΠΎΠ²
					type: "separator",
				}),
				new MenuItem({
					label: "Option 2",
					click() {
						console.log("Option 2 clicked");
					},
				}),
			],
		})
	);
 
	// примСняСм инстанс нашСго мСню Π² качСствС мСню прилоТСния
	Menu.setApplicationMenu(menu);
 
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		show: false,
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	window.on("ready-to-show", () => {
		window.show();
	});
 
	window.webContents.openDevTools();
});

Π’Π°ΠΊ ΠΆΠ΅ Π΅ΡΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ способ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²ΠΎΠ΅ мСню, Ρ‡Π΅Ρ€Π΅Π· Menu.buildFromTemplate([{}])

const menu = new Menu.buildFromTemplate([
	{
		label: "MyApp",
		submenu: [
			{
				label: "option 1",
				click() {
					console.log("Option 1 is clicked");
				},
			},
			{
				type: "separator",
			},
			{
				label: "option 2",
				click() {
					console.log("Option 2 is clicked");
				},
			},
		],
	},
]);

|400

Π‘Π°ΠΌΠΎΠ΅ основноС удобство послСднСго ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ вынСсти шаблон Π² любоС Π΄Ρ€ΡƒΠ³ΠΎΠ΅ мСсто ΠΊΠΎΠ΄Π° ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Ρ€Π°Π·Π²ΠΎΠ΄ΠΈΡ‚ΡŒ мусорку

Π’Π°ΠΊ ΠΆΠ΅ элСктрон позволяСт Π½Π°ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π΅Π³ΠΎ собствСнными элСмСнтами мСню Π² нашСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ

const menuTemplate = [
	{
		label: "MyApp",
		submenu: [
			{ role: "about" },
			{ type: "separator" },
			{ role: "services" },
			{ role: "hide" },
			{ role: "hideothers" },
			{ role: "unhide" },
			{ role: "quit" },
		],
	},
];

Π’Π°ΠΊ ΠΆΠ΅ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Ρ‹ Π² Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ прилоТСния

const menuTemplate = [
	{
		label: "MyApp",
		submenu: [
			{ role: "about" },
			{ type: "separator" },
			{ role: "services" },
			{ role: "hide" },
			{ role: "hideothers" },
			{ role: "unhide" },
			{ role: "quit" },
		],
	},
	{
		label: "MyMenu",
		submenu: [
			{
				label: "Option 1",
				click() {
					console.log("Option 1");
				},
			},
		],
	},
];

|400

А Ρ‚ΡƒΡ‚ ΡƒΠΆΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ создания контСкстного мСню, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ вызываСтся Π½Π° ПКМ

// шаблон контСкстного мСню
const contextMenuTemplate = [
	{ role: "about" },
	{ type: "separator" },
	{ label: "option 1" },
	{ label: "option 2" },
];
 
// созданиС контСкстного мСню
const contextMenu = new Menu.buildFromTemplate(contextMenuTemplate);
 
// созданиС окна
const createWindow = () => {
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		show: false,
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	window.on("ready-to-show", () => {
		window.show();
	});
 
	// ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ контСкстного мСню, Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ½ΠΎ ΠΏΠΎΡΠ²Π»ΡΡ‚ΡŒΡΡ
	window.webContents.on("context-menu", (e, params) => {
		contextMenu.popup(window, params.x, params.y);
	});
};

013 ΠœΠΎΠ΄ΡƒΠ»ΡŒ Tray

Π­Ρ‚ΠΎΡ‚ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ позволяСт ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΈΠΊΠΎΠ½ΠΊΡƒ трСя нашСго прилоТСния.

ΠŸΠ΅Ρ€Π²Ρ‹ΠΌ Π΄Π΅Π»ΠΎΠΌ, Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π² Π²Π΅Π±ΠΏΠ°ΠΊ Π»ΠΎΠ°Π΄Π΅Ρ€, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ изобраТСния Π² наш Π²Ρ‹Π²ΠΎΠ΄Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚.

npm install file-loader --save-dev
module.exports = {
	renderer: {
		entry: "./src/renderer/javascripts/index.js",
	},
	preload: {
		entry: "./src/preload/index.js",
	},
	main: {
		entry: "./src/main/index.js",
		//
		module: {
			rules: [
				// наастраиваСм ΠΏΠ΅Ρ€Π²ΠΎΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ для Π»ΠΎΠ°Π΄Π΅Ρ€Π°
				{
					test: /\.(png|jpe?g|gif)$/i,
					use: [
						{
							// Π²Ρ‹Π±ΠΈΡ€Π°Π΅ΠΌ Π»ΠΎΠ°Π΄Π΅Ρ€
							loader: "file-loader",
							options: {
								// ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½ компиляции
								name: "[path][name].[ext]",
							},
						},
					],
				},
			],
		},
	},
};

По сути ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π΅Π±ΠΏΠ°ΠΊ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Π» Ρ„Π°ΠΉΠ» со своим ΠΈΠΌΠ΅Π½Π΅ΠΌ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π² ΠΊΠΎΠ½Ρ†Π΅ Ρƒ ΠΈΠΊΠΎΠ½ΠΊΠΈ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ суффикс Template, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π° ΠΌΠ°ΠΊ-устройствах ΠΈΠΊΠΎΠ½ΠΊΠ° выполняла свою Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΡŽ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ

Π”Π°Π»ΡŒΡˆΠ΅ ΡƒΠΆΠ΅ создаём инстанс трСя со всСми Π²Ρ…ΠΎΠ΄Π½Ρ‹ΠΌΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ

import path from "path";
import { app, BrowserWindow, Tray } from "electron";
import icon from "trayTemplate.png";
 
const createWindow = () => {
	// new Tray() - Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΡƒ Π² Ρ‚Ρ€Π΅Π΅
	// ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎ Ρ‡Π΅Ρ€Π΅Π· path.resolve ΠΌΡ‹ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ ΠΊ ΠΈΠΊΠΎΠ½ΠΊΠ΅ для прилоТСния
	const tray = new Tray(path.resolve(__dirname, icon));
 
	// Π’Ρ‹Π²Π΅Π΄Π΅Ρ‚ тСкст ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ Π½Π° ΠΈΠΊΠΎΠ½ΠΊΡƒ
	tray.setToolTip("Electron Application");
 
	tray.on("click", () => {
		window.isVisible() ? window.hide() : window.show();
	});
 
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		show: false,
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	window.on("ready-to-show", () => {
		window.show();
	});
};
 
app.on("ready", () => {
	createWindow();
});

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ саму ΠΈΠΊΠΎΠ½ΠΊΡƒ прилоТСния Π² Ρ‚Ρ€Π΅Π΅, Π΅Π³ΠΎ Ρ‚ΡƒΠ»Ρ‚ΠΈΠΏ ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ, которая повСшана Π½Π° Ρ‚ΡƒΠ»Ρ‚ΠΈΠΏ. Π’Π°ΠΊ ΠΆΠ΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ΄ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ Π½Π° Ρ€Π°Π·Π½Ρ‹Π΅ ΠΊΠ»ΠΈΠΊΠΈ ΠΌΡ‹ΡˆΡŒΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΠΊΡƒ.

И Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠ΅Π½ΡŽΡˆΠΊΡƒ для нашСго трСя:

import path from "path";
import { app, BrowserWindow, Tray, Menu } from "electron";
import icon from "trayTemplate.png";
 
const createWindow = () => {
	// создаём контСкстноС мСню для трСя
	const trayMenu = new Menu.buildFromTemplate([
		{
			label: "Toggle App",
			click: () => {
				window.isVisible() ? window.hide() : window.show();
			},
		},
		{
			role: "quit",
		},
	]);
 
	const tray = new Tray(path.resolve(__dirname, icon));
 
	// присваиваСм контСкстноС мСню для трСя
	tray.setContextMenu(trayMenu);
	tray.setToolTip("Electron Application");
 
	tray.on("click", () => {
		window.isVisible() ? window.hide() : window.show();
	});
 
	let window = new BrowserWindow({
		width: 1280,
		height: 720,
		show: false,
		webPreferences: {
			nodeIntegration: true,
		},
	});
 
	window.loadFile("renderer/index.html");
 
	window.on("ready-to-show", () => {
		window.show();
	});
};
 
app.on("ready", () => {
	createWindow();
});

На ПКМ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° туглится, Π½Π° Π›ΠšΠœ открываСтся мСнюшка

|400