ContextElectron компонент, элемент навигации по приложению.

Структура папок.

context
¦
¦   index.js
¦
L---client // Все что относится к клиенту
    ¦   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 Context {
    constructor(parent) {
        // Создаем окно
        this.root = new BrowserWindow({
            frame: false, // Убираем рамку 
            transparent: true, // Устанавливаем прозрачность
            resizable: false, // Запрещаем масштабирование
            show: false, // Запрещаем показывать окно после загрузки 
            width: 170,
            height: 235,
            parent
        })

        // Загружаем страницу
        this.root.loadURL(`${__dirname}/client/index.html`)
        
        // Этот метод хранит callback обновления 
        this.cb_update = () => {}
        
        // Если окно теряет фокус то оно скрывается
        this.root.on('blur', () => {
            this.root.hide()
        })
    }

    ready() {
        // Ожидаем пока окно полностью инициализируется
        return new Promise(res => {
            this.root.once('ready-to-show', res)
        })
    }

    show() {
    	// Показываем окно и устанавливаем фокус
        this.root.show()
        this.root.focus()
    }

    hide() {
    	// Скрываем окно
        this.root.hide()
    }

    onCheckIP(cb) {
    	// Устанавливаем обработчик сигнала от окна (чек IP)
        ipcMain.on('CONTEXT_CHECKIP', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }

    onUpdate(cb) {
    	// Передаем оригинальную функцию 
        this.cb_update = cb
        // Устанавливаем обработчик сигнала от окна (Обновление серверов)
        ipcMain.on('CONTEXT_UPDATE', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }

    update() {
    	// Имитируем вызов onUpdate
        this.cb_update()
    }

    onSetting(cb) {
    	// Устанавливаем обработчик сигнала от окна (Настройки)
        ipcMain.on('CONTEXT_SETTING', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }

    onCallback(cb) {
    	// Устанавливаем обработчик сигнала от окна (Обратная связь)
        ipcMain.on('CONTEXT_CALLBACK', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }

    onHidden(cb) {
    	// Устанавливаем обработчик сигнала от окна (Свернуть)
        ipcMain.on('CONTEXT_HIDDEN', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }

    onExit(cb) {
    	// Устанавливаем обработчик сигнала от окна (Выйти)
        ipcMain.on('CONTEXT_EXIT', e => {
            this.hide()
            cb()
            e.returnValue = 'ok'
        })
    }
}


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'>
</head>
<body>
<div class='body'>
    <div class='btn' id='ip'>Определить IP</div>
    <div class='btn' id='update'>Обновить сервера</div>
    <div class='btn' id='setting'>Настройки</div>
    <div class='btn' id='about'>Обратная связь</div>
    <div class='btn' id='hidden'>Свернуть</div>
    <div class='btn end' id='exit'>Выход</div>
</div>
<script>
const { ipcRenderer, remote } = require('electron')

// Получаем контроль над окном
const win = remote.getCurrentWindow()

// Устанавливаем позицию окна основываясь на позиции курсора
setInterval(() => {
    win.setPosition(
        parseInt(localStorage.x) +
        parseInt(localStorage.context_x) - 168,
        parseInt(localStorage.y) +
        parseInt(localStorage.context_y) - 233
    )
}, 3)

// Отправляем компоненту сигнал "CONTEXT_CHECKIP"
document.getElementById('ip').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_CHECKIP')
})

// Отправляем компоненту сигнал "CONTEXT_UPDATE"
document.getElementById('update').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_UPDATE')
})

// Отправляем компоненту сигнал "CONTEXT_SETTING"
document.getElementById('setting').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_SETTING')
})

// Отправляем компоненту сигнал "CONTEXT_CALLBACK"
document.getElementById('about').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_CALLBACK')
})

// Отправляем компоненту сигнал "CONTEXT_HIDDEN"
document.getElementById('hidden').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_HIDDEN')
})

// Отправляем компоненту сигнал "CONTEXT_EXIT"
document.getElementById('exit').addEventListener('click', () => {
    ipcRenderer.send('CONTEXT_EXIT')
})
</script>
</body>
</html>


style.css — Стили для страницы.

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;
}

@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;
}

@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;
}

@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;
}

@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;
}

@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;
}

@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 {
    border-radius: 10px 10px 5px 10px;
    background: rgba(36, 39, 39, 0.9);
    padding: 10px 0px 10px 0px;
    height: 215px;
    font-size: 0px;
}

.btn {
    font-size: 14px;
    user-select: none;
    cursor: pointer;
    color: #eee;
    width: 170px;
    height: 35px;
    display: flex;
    justify-content: center;
    align-items: center;
    border-bottom: 1px solid rgba(36, 39, 39, 0.05);
}

.btn:hover {
    background: rgba(51, 54, 54, 0.6);
}

.end {
    border: none;
}


Application

Использование в приложении: /app/Сontext.

API

Интерфейс компонента Сontext.

const { app }   = require('electron')
    , VPN       = require('./../../app/components/vpn')
    , CONTEXT   = require('./../../app/components/context')

app.on('ready', async() => {

    const Vpn   = new VPN(),
        Context = new CONTEXT(Vpn.root)

    // Только после того как окна инициализируются программа продолжит исполнятся
    await Promise.all([
        Context.ready(),
        Vpn.ready()
    ])

    Vpn.show()
    Vpn.showTray()

    Vpn.onContext(() => Context.show())

    // обработчики  
    Context.onCheckIP(() => {
        console.log('Определить IP')
    })

    Context.onUpdate(() => {
        console.log('Обновить сервера')
    })

    Context.onSetting(() => {
        console.log('Настройки')
    })

    Context.onCallback(() => {
        console.log('Обратная связь')
    })

    Context.onHidden(() => {
        console.log('Свернуть')
    })

    Context.onExit(() => {
        console.log('Выход')
    })

})

Test

Версия для тестирования: /app_test/Сontext.

image

8 часть — Setting компонент


Собственный VPN клиент на JavaScript by JSus

Комментарии (0)