fix desktop
This commit is contained in:
@@ -352,11 +352,11 @@ Renderer остался «чистым» фронтом: получает `windo
|
||||
|
||||
## Глава 4. Секретный Go-движок внутри
|
||||
|
||||
Написан маленький Go-хелпер, который делает РОВНО то, что нужно:
|
||||
Написан маленький Go-хелпер, который делает кнокинг портов в соответствии с конфигурацией:
|
||||
|
||||
- читает из stdin JSON: `targets`, `delay`, `gateway`,
|
||||
- превращает в конфиг,
|
||||
- вызывает `internal.PortKnocker()` (в нём `SO_BINDTODEVICE`, `LocalAddr`, TCP/UDP),
|
||||
- превращает их в конфиг,
|
||||
- вызывает `internal.PortKnocker()` (в нём `SO_BINDTODEVICE`),
|
||||
- печатает в stdout один короткий JSON: «успех/ошибка».
|
||||
|
||||
```go
|
||||
@@ -512,7 +512,7 @@ clearTimeout(timeout);
|
||||
|
||||
## Глава 6. UI только для UI
|
||||
|
||||
В `renderer` ничего такого что непосредственно работает с ядром системы.
|
||||
В `renderer` ничего такого что непосредственно работает с ядром системы.
|
||||
Собираем `targets`, `delay`, забираем `gateway` с формы — и даём команду:
|
||||
|
||||
```js
|
||||
@@ -552,18 +552,18 @@ Renderer ничего не знает про сокеты, туннели и Go.
|
||||
|
||||
При разработке запускаем `npm run dev` — он сначала соберёт Go, потом стартанёт Electron. В проде `electron-builder` положит бинарь в `resources/bin`. Пользователь вообще не в курсе, что внутри слишком умный Go сидит и пинает пакеты в нужные цели.
|
||||
|
||||
Можно конечно и не Го-хелпер запилить - например на Rust или на С++
|
||||
Можно конечно и не Го-хелпер запилить - например на Rust (смотри последнюю версию проекта в репозитории) или на С++
|
||||
|
||||
---
|
||||
|
||||
## Глава 8. Почему мы пошли этим путём (немного философии)
|
||||
## Глава 8. Почему именно так
|
||||
|
||||
- Node — шикарен для UI и связки слоёв, но ему не хватает «низкоуровневого директа» в сокетах.
|
||||
- Go умеет то, что нам нужно: `SO_BINDTODEVICE`, привязка к интерфейсу, «я сказал — поедешь тут».
|
||||
- Electron — как контейнер: упаковали веб, настроили мосты, подложили Go, включили DevTools — красота.
|
||||
- Node — хорош для UI и связки слоёв, но ему не хватает «низкоуровневого директа» в сокетах.
|
||||
- Go умеет то, что нужно: `SO_BINDTODEVICE`, привязка к интерфейсу.
|
||||
- Electron — как контейнер: упаковали веб, настроили мосты, подложили Go, включили DevTools = красота.
|
||||
|
||||
Минус: надо собирать маленький бинарь.
|
||||
Плюс: он работает невидимо и делает «как надо».
|
||||
Минус: надо собирать маленький бинарничек, который немного увеличит размер пакета (так как он и так ого-го-то несущественно).
|
||||
Плюс: он работает невидимо и делает что требуется.
|
||||
|
||||
---
|
||||
|
||||
@@ -573,13 +573,209 @@ Renderer ничего не знает про сокеты, туннели и Go.
|
||||
- Следите за stdout хелпера — там должен быть только JSON (мы жёстко это контролируем).
|
||||
- Путь к бинарю в деве и проде разный — мы это учли (ищем сначала `bin/`, потом `resources/bin`).
|
||||
|
||||
Мем-чекилст:
|
||||
- [x] «Всё уходит в WireGuard» → ставим `gateway` → Go рулит.
|
||||
- [x] «JSON не парсится» → убрали verbose → теперь парсится.
|
||||
- [x] «Где бинарь?» → смотрим `resources/bin`.
|
||||
---
|
||||
|
||||
## Эпилог
|
||||
|
||||
Мы сделали десктопное приложение, которое вообще-то «веб», но изнутри умеет кое что еще.
|
||||
|
||||
---
|
||||
|
||||
## Эпилог: помогло?
|
||||
## А как же фреймворки?
|
||||
|
||||
Мы сделали десктопное приложение, которое вообще-то «веб», но изнутри умеет очень взрослые вещи. Пользователь нажимает кнопку — а Go в это время спорит с системой маршрутизации, выигрывает и бьёт туда, куда надо.
|
||||
На Vanilla js все просто и понятно писать но очень многсловно и трудно сделать все структурировано и красиво "по фен-шую".
|
||||
Давайте коротенько рассмотрим, а как же нам портировать имеющийся ui ангуляр проект, который героически был вшит в go-knocker в десктопном проекте electron.
|
||||
|
||||
Итак, у нас есть готовый или не очень Angular проект который уже работает как веб-приложение. Теперь нужно интегрировать его в Electron так, чтобы получить все возможности поюзать его как графическое приложение.
|
||||
|
||||
### Архитектурное решение
|
||||
|
||||
Мы создали отдельную папку `desktop-angular/`, которая содержит:
|
||||
|
||||
1. **Electron обертку** - основной процесс и настройки
|
||||
2. **Копию Angular проекта** в `src/frontend/` - для удобства разработки
|
||||
3. **IPC сервисы** - для взаимодействия с нативным кодом
|
||||
4. **Кастомные модальные окна** - нативные диалоги Electron
|
||||
|
||||
### Структура проекта
|
||||
|
||||
``` text
|
||||
desktop-angular/
|
||||
├── src/
|
||||
│ ├── main/ # Electron main process
|
||||
│ │ ├── main.js # Основной процесс
|
||||
│ │ ├── modal.html # Кастомные модальные окна
|
||||
│ │ ├── open-dialog.html # Диалог открытия файлов
|
||||
│ │ └── save-dialog.html # Диалог сохранения файлов
|
||||
│ ├── preload/ # Безопасный мост
|
||||
│ │ └── preload.js # API для рендерера
|
||||
│ └── frontend/ # Angular приложение
|
||||
│ ├── src/app/
|
||||
│ │ ├── ipc.service.ts # Сервис для IPC
|
||||
│ │ ├── modal.service.ts # Сервис модальных окон
|
||||
│ │ └── root.component.ts # Главный компонент
|
||||
│ └── package.json # Зависимости Angular
|
||||
├── package.json # Конфигурация Electron
|
||||
└── bin/ # Скомпилированный Go бэкенд
|
||||
```
|
||||
|
||||
|
||||
### Ключевые особенности реализации
|
||||
|
||||
#### 1. Двойной режим работы
|
||||
|
||||
В `main.js` реализована логика, которая определяет режим работы:
|
||||
|
||||
```javascript
|
||||
const isDev = process.env.NODE_ENV !== "production" && !app.isPackaged;
|
||||
|
||||
if (isDev) {
|
||||
// В режиме разработки загружаем с ng serve
|
||||
win.loadURL('http://localhost:4200');
|
||||
win.webContents.openDevTools();
|
||||
} else {
|
||||
// В продакшене загружаем собранные файлы
|
||||
const indexPath = app.isPackaged
|
||||
? path.join(process.resourcesPath, 'ui-dist', 'index.html')
|
||||
: path.resolve(__dirname, '../frontend/dist/project-front/browser/index.html');
|
||||
win.loadFile(indexPath);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. IPC сервис для Angular
|
||||
|
||||
Создан специальный сервис `IpcService`, который предоставляет удобный API для взаимодействия с Electron:
|
||||
|
||||
```typescript
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class IpcService {
|
||||
|
||||
async showNativeModal(config: ModalConfig): Promise<string> {
|
||||
return await (window as any).api.showNativeModal(config);
|
||||
}
|
||||
|
||||
async openFileDialog(config: FileDialogConfig): Promise<string[]> {
|
||||
return await (window as any).api.openFileDialog(config);
|
||||
}
|
||||
|
||||
async saveFileDialog(config: SaveDialogConfig): Promise<string> {
|
||||
return await (window as any).api.saveFileDialog(config);
|
||||
}
|
||||
|
||||
async loadFileContent(filePath: string): Promise<string> {
|
||||
return await (window as any).api.loadFileContent(filePath);
|
||||
}
|
||||
|
||||
async saveFileContent(filePath: string, content: string): Promise<void> {
|
||||
return await (window as any).api.saveFileContent(filePath, content);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Кастомные нативные диалоги
|
||||
|
||||
Вместо стандартных системных диалогов созданы кастомные HTML/CSS/JS диалоги, которые:
|
||||
|
||||
- Работают даже если Angular UI "зависла"
|
||||
- Имеют единый стиль с приложением
|
||||
- Поддерживают превью файлов
|
||||
- Имеют расширенную функциональность
|
||||
|
||||
#### 4. Интеграция с Go бэкендом
|
||||
|
||||
Angular приложение работает с тем же Go бэкендом, что и веб-версия:
|
||||
|
||||
```typescript
|
||||
export class KnockService {
|
||||
private apiBase = 'http://localhost:8080/api/v1';
|
||||
|
||||
async knock(config: KnockConfig): Promise<KnockResult> {
|
||||
const response = await fetch(`${this.apiBase}/knock`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(config)
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Скрипты сборки
|
||||
|
||||
В `package.json` настроены удобные команды:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "concurrently -k -n UI,ELECTRON -c green,cyan \"cd src/frontend && npm start\" \"wait-on http://localhost:4200 && cross-env NODE_ENV=development electron .\"",
|
||||
"build:ui": "cd src/frontend && npm run build",
|
||||
"go:build": "bash -lc 'mkdir -p bin && cd ../back && go build -o ../desktop-angular/bin/full-go-knocker .'",
|
||||
"dist": "npm run build:ui && npm run go:build && cross-env NODE_ENV=production electron-builder"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Конфигурация упаковки
|
||||
|
||||
Electron Builder настроен для включения всех необходимых файлов:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"files": [
|
||||
"src/main/**/*",
|
||||
"src/preload/**/*",
|
||||
"package.json",
|
||||
"bin/**/*"
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "src/frontend/dist/project-front/browser",
|
||||
"to": "ui-dist"
|
||||
},
|
||||
{
|
||||
"from": "bin",
|
||||
"to": "bin"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Преимущества такого подхода
|
||||
|
||||
1. **Переиспользование кода** - Angular приложение остается тем же самым
|
||||
2. **Нативные возможности** - доступ к файловой системе, системным диалогам
|
||||
3. **Единая кодовая база** - один Angular проект для веба и десктопа
|
||||
4. **Удобная разработка** - hot reload в режиме разработки
|
||||
5. **Простая сборка** - автоматическая упаковка всех компонентов
|
||||
|
||||
### Результат
|
||||
|
||||
Получилось полноценное десктопное приложение, которое:
|
||||
|
||||
- Выглядит и работает как нативное
|
||||
- Использует весь функционал Angular
|
||||
- Интегрировано с Go бэкендом
|
||||
- Имеет кастомные нативные диалоги
|
||||
- Упаковывается в единый исполняемый файл
|
||||
|
||||
Это решение демонстрирует, как можно элегантно интегрировать современный веб-фреймворк в десктопное приложение, сохраняя все преимущества обеих платформ.
|
||||
|
||||
---
|
||||
|
||||
## Заключение
|
||||
|
||||
Мы рассмотрели два подхода к созданию десктопных приложений:
|
||||
|
||||
1. **Vanilla JavaScript** - простой, быстрый, но многословный
|
||||
2. **Angular интеграция** - структурированный, переиспользуемый, но более сложный
|
||||
|
||||
Оба подхода имеют свои преимущества и недостатки. Выбор зависит от ваших потребностей:
|
||||
|
||||
- Для быстрого прототипа или простого UI - Vanilla JS
|
||||
- Для сложного приложения с переиспользованием веб-кода - Angular
|
||||
|
||||
Главное - правильно спроектировать архитектуру взаимодействия между Electron и вашим UI, используя IPC и preload скрипты для безопасной передачи данных.
|
||||
|
Reference in New Issue
Block a user