P.S. Каждая часть — это часть, сама по себе смысла не имеет, чтобы обзавестись необходимым контекстом и не испытывать когнитивный диссонанс от отсутствия так необходимых блоков текста начните читать с 1 части
Callback — Electron компонент, элемент обратной связи.
Структура папок:
index.js — Файл, в котором создается Electron компонент.
Cодержимое файла index.js.
index.html — HTML-страница окна.
Cодержимое файла index.html:
style.css — HTML-страница окна.
Cодержимое файла style.css:
Application
Использование в приложении: /app/Callback
API
Интерфейс компонента Callback:
Test
Версия для тестирования: /app_test/Callback
10 часть — Объединение всех компонентов
Callback — Electron компонент, элемент обратной связи.
Структура папок:
callback
¦
¦ index.js
¦
L---client // Все что относится к клиенту
¦ image.jpg
¦ index.html
¦ style.css
¦
L---fonts
font1.woff2
font2.woff2
font3.woff2
font4.woff2
font5.woff2
font6.woff2
font7.woff2
index.js — Файл, в котором создается Electron компонент.
Cодержимое файла index.js.
Код
const { BrowserWindow, ipcMain } = require('electron')
module.exports = class Callback {
constructor(parent) {
// Создаем окно
this.root = new BrowserWindow({
frame: false, // Убираем рамку
transparent: true, // Убираем рамку
resizable: false, // Запрещаем масштабирование
show: false, // Запрещаем показывать окно после загрузки
width: 175,
height: 463,
center: true,
parent
})
// Загружаем страницу
this.root.loadURL(`${__dirname}/client/index.html`)
// Устанавливаем обработчик сигнала от окна (закрытие окна)
ipcMain.on('CALLBACK_CLOSE', e => {
this.root.hide()
e.returnValue = 'ok'
})
}
ready() {
// Ожидаем пока окно полностью инициализируется
return new Promise(res => {
this.root.once('ready-to-show', res)
})
}
show() {
// Показываем окно
this.root.show()
}
hide() {
// Скрываем окно
this.root.hide()
}
}
index.html — HTML-страница окна.
Cодержимое файла index.html:
Код
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<link rel='stylesheet' type='text/css' href='style.css?ss'>
</head>
<body>
<div class='body'>
<div class='avatar'></div>
<div class='info'>
<div class='name'><b>JSus</b> Dev</div>
<div class='background'><i>"JavaScript программист и разработчик электронных устройств"</i></div>
<a onclick='open_link("https://github.com/JsusDev/JS.VPN-Client");event.preventDefault()' href='#' class='gh'>GitHub</a>
<a onclick='open_link("https://...");event.preventDefault()' href='#' target='_blank'>Telegram me</a>
<a onclick='open_link("https://...");event.preventDefault()' href='#' target='_blank'>Telegram channel</a>
<div class='btn'>Закрыть</div>
</div>
</div>
<script>
const btn = document.getElementsByClassName('btn')[0]
, { ipcRenderer, shell } = require('electron')
// Открывает ссылки в вашем браузере по умолчанию
const open_link = (url) => shell.openExternal(url)
// Отправляет сигнал CALLBACK_CLOSE (Скрытие окна)
btn.addEventListener('click', () => {
ipcRenderer.sendSync('CALLBACK_CLOSE')
})
</script>
</body>
</html>
style.css — HTML-страница окна.
Cодержимое файла style.css:
Код
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font1.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font2.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font3.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font4.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font5.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font6.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Source Sans Pro';
font-style: normal;
font-weight: 400;
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(fonts/font7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
* {
font-family: 'Source Sans Pro', sans-serif;
padding: 0;
margin: 0;
overflow: hidden;
background: rgba(0, 0, 0, 0);
}
.body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.avatar {
width: 120px;
height: 120px;
border-radius: 100%;
border: 13px solid #242424;
background: url('image.jpg');
background-size: cover;
}
.info {
margin-top: 10px;
font-size: 14px;
background: rgba(36, 39, 39, 0.9);
color: #eee;
width: 135px;
border-radius: 10px;
padding: 10px 20px 10px 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.name {
font-size: 23px;
margin-bottom: 10px;
}
.background {
text-align: center;
margin: 10px;
}
a {
user-select: none;
cursor: pointer;
width: 100%;
display: block;
color: #bbb;
text-decoration: none;
font-size: 13px;
}
a:hover {
color: #ccc;
}
.gh {
margin: 4px;
text-align: center;
margin-bottom: 10px;
}
.btn {
cursor: pointer;
margin-top: 2px;
padding: 4px 10px 4px 10px;
border-radius: 6px;
user-select: none;
margin: 10px 10px 0px 10px;
}
.btn:hover {
color: #ccc
}
Application
Использование в приложении: /app/Callback
API
Интерфейс компонента Callback:
const { app } = require('electron')
, CALLBACK = require('./../../app/components/callback')
app.on('ready', async() => {
const Callback = new CALLBACK()
await Callback.ready()
// Показываем окно
Callback.show()
})
Test
Версия для тестирования: /app_test/Callback
10 часть — Объединение всех компонентов
Навигация
1 часть — Вводная
2 часть — Разработка
3 часть — OpenVPN компонент
4 часть — Configs компонент
5 часть — Vpn компонент
6 часть — Notify компонент
7 часть — Context компонент
8 часть — Setting компонент
9 часть — Callback компонент
10 часть — Объединение всех компонентов
11 часть — Сборка приложения под Windows
2 часть — Разработка
3 часть — OpenVPN компонент
4 часть — Configs компонент
5 часть — Vpn компонент
6 часть — Notify компонент
7 часть — Context компонент
8 часть — Setting компонент
9 часть — Callback компонент
10 часть — Объединение всех компонентов
11 часть — Сборка приложения под Windows