@alphamatica/app-updater 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -52
- package/LICENSE +7 -7
- package/README.md +186 -186
- package/dist/ui.d.ts +8 -3
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +352 -84
- package/dist/ui.js.map +1 -1
- package/dist/updater.d.ts +26 -0
- package/dist/updater.d.ts.map +1 -1
- package/dist/updater.js +251 -11
- package/dist/updater.js.map +1 -1
- package/package.json +2 -2
package/dist/ui.js
CHANGED
|
@@ -2,15 +2,162 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UpdaterUI = void 0;
|
|
4
4
|
const electron_1 = require("electron");
|
|
5
|
+
const COMMON_STYLES = `
|
|
6
|
+
* {
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: 0;
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
}
|
|
11
|
+
body {
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
13
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
14
|
+
min-height: 100vh;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
-webkit-app-region: drag;
|
|
20
|
+
}
|
|
21
|
+
.card {
|
|
22
|
+
background: white;
|
|
23
|
+
border-radius: 16px;
|
|
24
|
+
padding: 32px;
|
|
25
|
+
width: 100%;
|
|
26
|
+
max-width: 400px;
|
|
27
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
28
|
+
-webkit-app-region: no-drag;
|
|
29
|
+
}
|
|
30
|
+
.icon {
|
|
31
|
+
width: 64px;
|
|
32
|
+
height: 64px;
|
|
33
|
+
margin: 0 auto 20px;
|
|
34
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
}
|
|
40
|
+
.icon svg {
|
|
41
|
+
width: 32px;
|
|
42
|
+
height: 32px;
|
|
43
|
+
fill: white;
|
|
44
|
+
}
|
|
45
|
+
h2 {
|
|
46
|
+
font-size: 20px;
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
color: #1a1a2e;
|
|
49
|
+
text-align: center;
|
|
50
|
+
margin-bottom: 8px;
|
|
51
|
+
}
|
|
52
|
+
.version {
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
color: #667eea;
|
|
55
|
+
text-align: center;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
margin-bottom: 16px;
|
|
58
|
+
}
|
|
59
|
+
.description {
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
color: #666;
|
|
62
|
+
text-align: center;
|
|
63
|
+
line-height: 1.5;
|
|
64
|
+
margin-bottom: 24px;
|
|
65
|
+
}
|
|
66
|
+
.buttons {
|
|
67
|
+
display: flex;
|
|
68
|
+
gap: 12px;
|
|
69
|
+
}
|
|
70
|
+
button {
|
|
71
|
+
flex: 1;
|
|
72
|
+
padding: 14px 20px;
|
|
73
|
+
border: none;
|
|
74
|
+
border-radius: 10px;
|
|
75
|
+
font-size: 14px;
|
|
76
|
+
font-weight: 600;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
transition: all 0.2s ease;
|
|
79
|
+
}
|
|
80
|
+
button:hover {
|
|
81
|
+
transform: translateY(-2px);
|
|
82
|
+
}
|
|
83
|
+
button:active {
|
|
84
|
+
transform: translateY(0);
|
|
85
|
+
}
|
|
86
|
+
.btn-primary {
|
|
87
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
88
|
+
color: white;
|
|
89
|
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
90
|
+
}
|
|
91
|
+
.btn-primary:hover {
|
|
92
|
+
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
|
|
93
|
+
}
|
|
94
|
+
.btn-secondary {
|
|
95
|
+
background: #f0f0f0;
|
|
96
|
+
color: #666;
|
|
97
|
+
}
|
|
98
|
+
.btn-secondary:hover {
|
|
99
|
+
background: #e5e5e5;
|
|
100
|
+
}
|
|
101
|
+
.progress-container {
|
|
102
|
+
margin-bottom: 16px;
|
|
103
|
+
}
|
|
104
|
+
.progress-bar {
|
|
105
|
+
width: 100%;
|
|
106
|
+
height: 8px;
|
|
107
|
+
background: #e0e0e0;
|
|
108
|
+
border-radius: 4px;
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
}
|
|
111
|
+
.progress-fill {
|
|
112
|
+
height: 100%;
|
|
113
|
+
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
|
114
|
+
border-radius: 4px;
|
|
115
|
+
transition: width 0.15s ease-out;
|
|
116
|
+
width: 0%;
|
|
117
|
+
}
|
|
118
|
+
.progress-info {
|
|
119
|
+
display: flex;
|
|
120
|
+
justify-content: space-between;
|
|
121
|
+
margin-top: 12px;
|
|
122
|
+
font-size: 13px;
|
|
123
|
+
color: #666;
|
|
124
|
+
}
|
|
125
|
+
.progress-percent {
|
|
126
|
+
font-weight: 600;
|
|
127
|
+
color: #667eea;
|
|
128
|
+
}
|
|
129
|
+
.progress-speed {
|
|
130
|
+
color: #999;
|
|
131
|
+
}
|
|
132
|
+
.spinner {
|
|
133
|
+
width: 48px;
|
|
134
|
+
height: 48px;
|
|
135
|
+
margin: 0 auto 20px;
|
|
136
|
+
border: 3px solid #e0e0e0;
|
|
137
|
+
border-top-color: #667eea;
|
|
138
|
+
border-radius: 50%;
|
|
139
|
+
animation: spin 1s linear infinite;
|
|
140
|
+
}
|
|
141
|
+
@keyframes spin {
|
|
142
|
+
to { transform: rotate(360deg); }
|
|
143
|
+
}
|
|
144
|
+
`;
|
|
145
|
+
const DOWNLOAD_ICON = `<svg viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>`;
|
|
146
|
+
const UPDATE_ICON = `<svg viewBox="0 0 24 24"><path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/></svg>`;
|
|
147
|
+
const CHECK_ICON = `<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>`;
|
|
5
148
|
class UpdaterUI {
|
|
6
149
|
constructor(options) {
|
|
7
|
-
this.
|
|
150
|
+
this.currentWindow = null;
|
|
151
|
+
this.lastProgress = null;
|
|
152
|
+
this.progressThrottleTimer = null;
|
|
8
153
|
this.options = {
|
|
9
154
|
autoCheck: true,
|
|
10
155
|
showNotification: true,
|
|
11
156
|
...options,
|
|
12
157
|
};
|
|
13
158
|
this.updater = options.updater;
|
|
159
|
+
// UI управляет установкой вручную — отключаем autoInstall
|
|
160
|
+
this.updater.disableAutoInstall();
|
|
14
161
|
this.setupListeners();
|
|
15
162
|
this.setupIPC();
|
|
16
163
|
}
|
|
@@ -27,7 +174,7 @@ class UpdaterUI {
|
|
|
27
174
|
this.showInstallDialog(info);
|
|
28
175
|
});
|
|
29
176
|
this.updater.on('error', error => {
|
|
30
|
-
|
|
177
|
+
this.showErrorDialog(error.message);
|
|
31
178
|
});
|
|
32
179
|
}
|
|
33
180
|
setupIPC() {
|
|
@@ -44,119 +191,240 @@ class UpdaterUI {
|
|
|
44
191
|
return this.updater.getUpdateInfo();
|
|
45
192
|
});
|
|
46
193
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
detail: info.notes || 'Хотите скачать обновление?',
|
|
53
|
-
buttons: ['Скачать', 'Позже'],
|
|
54
|
-
defaultId: 0,
|
|
55
|
-
cancelId: 1,
|
|
56
|
-
});
|
|
57
|
-
if (result.response === 0) {
|
|
58
|
-
this.showProgressWindow();
|
|
59
|
-
await this.updater.downloadUpdate();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async showInstallDialog(info) {
|
|
63
|
-
this.closeProgressWindow();
|
|
64
|
-
const result = await electron_1.dialog.showMessageBox({
|
|
65
|
-
type: 'info',
|
|
66
|
-
title: 'Обновление загружено',
|
|
67
|
-
message: `Версия ${info.version} готова к установке`,
|
|
68
|
-
detail: 'Приложение будет перезапущено для завершения обновления.',
|
|
69
|
-
buttons: ['Установить сейчас', 'Позже'],
|
|
70
|
-
defaultId: 0,
|
|
71
|
-
cancelId: 1,
|
|
72
|
-
});
|
|
73
|
-
if (result.response === 0) {
|
|
74
|
-
await this.updater.installUpdate();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
showProgressWindow() {
|
|
78
|
-
this.progressWindow = new electron_1.BrowserWindow({
|
|
79
|
-
width: 400,
|
|
80
|
-
height: 150,
|
|
194
|
+
createWindow(width, height) {
|
|
195
|
+
this.closeCurrentWindow();
|
|
196
|
+
const win = new electron_1.BrowserWindow({
|
|
197
|
+
width,
|
|
198
|
+
height,
|
|
81
199
|
resizable: false,
|
|
82
200
|
minimizable: false,
|
|
83
201
|
maximizable: false,
|
|
84
|
-
closable:
|
|
202
|
+
closable: true,
|
|
85
203
|
frame: false,
|
|
204
|
+
transparent: true,
|
|
86
205
|
alwaysOnTop: true,
|
|
206
|
+
skipTaskbar: false,
|
|
87
207
|
webPreferences: {
|
|
88
208
|
nodeIntegration: true,
|
|
89
209
|
contextIsolation: false,
|
|
90
210
|
},
|
|
91
211
|
});
|
|
212
|
+
win.center();
|
|
213
|
+
this.currentWindow = win;
|
|
214
|
+
return win;
|
|
215
|
+
}
|
|
216
|
+
closeCurrentWindow() {
|
|
217
|
+
if (this.currentWindow && !this.currentWindow.isDestroyed()) {
|
|
218
|
+
this.currentWindow.close();
|
|
219
|
+
}
|
|
220
|
+
this.currentWindow = null;
|
|
221
|
+
}
|
|
222
|
+
showUpdateDialog(info) {
|
|
223
|
+
const win = this.createWindow(440, 340);
|
|
92
224
|
const html = `
|
|
93
225
|
<!DOCTYPE html>
|
|
94
226
|
<html>
|
|
95
227
|
<head>
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
228
|
+
<meta charset="utf-8">
|
|
229
|
+
<style>${COMMON_STYLES}</style>
|
|
230
|
+
</head>
|
|
231
|
+
<body>
|
|
232
|
+
<div class="card">
|
|
233
|
+
<div class="icon">${UPDATE_ICON}</div>
|
|
234
|
+
<h2>Доступно обновление</h2>
|
|
235
|
+
<div class="version">Версия ${info.version || 'N/A'}</div>
|
|
236
|
+
<div class="description">${info.notes || 'Доступна новая версия приложения. Рекомендуем обновиться для получения последних улучшений и исправлений.'}</div>
|
|
237
|
+
<div class="buttons">
|
|
238
|
+
<button class="btn-secondary" onclick="later()">Позже</button>
|
|
239
|
+
<button class="btn-primary" onclick="download()">Скачать</button>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
<script>
|
|
243
|
+
const { ipcRenderer } = require('electron');
|
|
244
|
+
function download() { ipcRenderer.send('updater-action', 'download'); }
|
|
245
|
+
function later() { ipcRenderer.send('updater-action', 'later'); }
|
|
246
|
+
</script>
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|
|
249
|
+
`;
|
|
250
|
+
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
251
|
+
electron_1.ipcMain.once('updater-action', async (_, action) => {
|
|
252
|
+
if (action === 'download') {
|
|
253
|
+
this.showProgressWindow();
|
|
254
|
+
await this.updater.downloadUpdate();
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
this.closeCurrentWindow();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
showProgressWindow() {
|
|
262
|
+
const win = this.createWindow(440, 280);
|
|
263
|
+
const html = `
|
|
264
|
+
<!DOCTYPE html>
|
|
265
|
+
<html>
|
|
266
|
+
<head>
|
|
267
|
+
<meta charset="utf-8">
|
|
268
|
+
<style>${COMMON_STYLES}</style>
|
|
269
|
+
</head>
|
|
270
|
+
<body>
|
|
271
|
+
<div class="card">
|
|
272
|
+
<div class="icon">${DOWNLOAD_ICON}</div>
|
|
273
|
+
<h2>Загрузка обновления</h2>
|
|
274
|
+
<div class="description" id="status">Подготовка к загрузке...</div>
|
|
275
|
+
<div class="progress-container">
|
|
276
|
+
<div class="progress-bar">
|
|
277
|
+
<div class="progress-fill" id="progress"></div>
|
|
278
|
+
</div>
|
|
279
|
+
<div class="progress-info">
|
|
280
|
+
<span class="progress-percent" id="percent">0%</span>
|
|
281
|
+
<span id="size">— / —</span>
|
|
282
|
+
<span class="progress-speed" id="speed">— МБ/с</span>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
<script>
|
|
287
|
+
const { ipcRenderer } = require('electron');
|
|
288
|
+
|
|
289
|
+
function formatBytes(bytes) {
|
|
290
|
+
if (!bytes || bytes === 0) return '—';
|
|
291
|
+
if (bytes < 1024) return bytes + ' Б';
|
|
292
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' КБ';
|
|
293
|
+
return (bytes / (1024 * 1024)).toFixed(1) + ' МБ';
|
|
105
294
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
overflow: hidden;
|
|
295
|
+
|
|
296
|
+
function formatSpeed(bytesPerSecond) {
|
|
297
|
+
if (!bytesPerSecond || bytesPerSecond === 0) return '— МБ/с';
|
|
298
|
+
if (bytesPerSecond < 1024) return bytesPerSecond + ' Б/с';
|
|
299
|
+
if (bytesPerSecond < 1024 * 1024) return (bytesPerSecond / 1024).toFixed(1) + ' КБ/с';
|
|
300
|
+
return (bytesPerSecond / (1024 * 1024)).toFixed(1) + ' МБ/с';
|
|
113
301
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
302
|
+
|
|
303
|
+
ipcRenderer.on('progress', (e, data) => {
|
|
304
|
+
document.getElementById('progress').style.width = data.percent + '%';
|
|
305
|
+
document.getElementById('percent').textContent = data.percent + '%';
|
|
306
|
+
document.getElementById('size').textContent = formatBytes(data.transferred) + ' / ' + formatBytes(data.total);
|
|
307
|
+
document.getElementById('speed').textContent = formatSpeed(data.bytesPerSecond);
|
|
308
|
+
document.getElementById('status').textContent = 'Загрузка...';
|
|
309
|
+
});
|
|
310
|
+
</script>
|
|
311
|
+
</body>
|
|
312
|
+
</html>
|
|
313
|
+
`;
|
|
314
|
+
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
315
|
+
}
|
|
316
|
+
showInstallDialog(info) {
|
|
317
|
+
const win = this.createWindow(440, 320);
|
|
318
|
+
const html = `
|
|
319
|
+
<!DOCTYPE html>
|
|
320
|
+
<html>
|
|
321
|
+
<head>
|
|
322
|
+
<meta charset="utf-8">
|
|
323
|
+
<style>${COMMON_STYLES}</style>
|
|
324
|
+
</head>
|
|
325
|
+
<body>
|
|
326
|
+
<div class="card">
|
|
327
|
+
<div class="icon">${CHECK_ICON}</div>
|
|
328
|
+
<h2>Обновление загружено</h2>
|
|
329
|
+
<div class="version">Версия ${info.version || 'N/A'}</div>
|
|
330
|
+
<div class="description">Обновление готово к установке. Приложение будет перезапущено для завершения обновления.</div>
|
|
331
|
+
<div class="buttons">
|
|
332
|
+
<button class="btn-secondary" onclick="later()">Позже</button>
|
|
333
|
+
<button class="btn-primary" onclick="install()">Установить</button>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
<script>
|
|
337
|
+
const { ipcRenderer } = require('electron');
|
|
338
|
+
function install() { ipcRenderer.send('updater-install-action', 'install'); }
|
|
339
|
+
function later() { ipcRenderer.send('updater-install-action', 'later'); }
|
|
340
|
+
</script>
|
|
341
|
+
</body>
|
|
342
|
+
</html>
|
|
343
|
+
`;
|
|
344
|
+
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
345
|
+
electron_1.ipcMain.once('updater-install-action', async (_, action) => {
|
|
346
|
+
if (action === 'install') {
|
|
347
|
+
this.showInstallingWindow();
|
|
348
|
+
await this.updater.installUpdate();
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
this.closeCurrentWindow();
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
showInstallingWindow() {
|
|
356
|
+
const win = this.createWindow(440, 260);
|
|
357
|
+
const html = `
|
|
358
|
+
<!DOCTYPE html>
|
|
359
|
+
<html>
|
|
360
|
+
<head>
|
|
361
|
+
<meta charset="utf-8">
|
|
362
|
+
<style>${COMMON_STYLES}</style>
|
|
363
|
+
</head>
|
|
364
|
+
<body>
|
|
365
|
+
<div class="card">
|
|
366
|
+
<div class="spinner"></div>
|
|
367
|
+
<h2>Установка обновления</h2>
|
|
368
|
+
<div class="description">Пожалуйста, подождите. Приложение будет перезапущено автоматически.</div>
|
|
369
|
+
</div>
|
|
370
|
+
</body>
|
|
371
|
+
</html>
|
|
372
|
+
`;
|
|
373
|
+
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
374
|
+
}
|
|
375
|
+
showErrorDialog(message) {
|
|
376
|
+
const win = this.createWindow(440, 300);
|
|
377
|
+
const errorIcon = `<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>`;
|
|
378
|
+
const html = `
|
|
379
|
+
<!DOCTYPE html>
|
|
380
|
+
<html>
|
|
381
|
+
<head>
|
|
382
|
+
<meta charset="utf-8">
|
|
383
|
+
<style>
|
|
384
|
+
${COMMON_STYLES}
|
|
385
|
+
.icon { background: linear-gradient(135deg, #ff6b6b 0%, #ee5a5a 100%); }
|
|
386
|
+
.btn-primary {
|
|
387
|
+
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a5a 100%);
|
|
388
|
+
box-shadow: 0 4px 15px rgba(255, 107, 107, 0.4);
|
|
118
389
|
}
|
|
119
|
-
.
|
|
120
|
-
|
|
121
|
-
font-size: 14px;
|
|
122
|
-
color: #666;
|
|
390
|
+
.btn-primary:hover {
|
|
391
|
+
box-shadow: 0 6px 20px rgba(255, 107, 107, 0.5);
|
|
123
392
|
}
|
|
124
393
|
</style>
|
|
125
394
|
</head>
|
|
126
395
|
<body>
|
|
127
|
-
<
|
|
128
|
-
|
|
129
|
-
<
|
|
396
|
+
<div class="card">
|
|
397
|
+
<div class="icon">${errorIcon}</div>
|
|
398
|
+
<h2>Ошибка обновления</h2>
|
|
399
|
+
<div class="description">${message}</div>
|
|
400
|
+
<div class="buttons">
|
|
401
|
+
<button class="btn-primary" onclick="close()">Закрыть</button>
|
|
402
|
+
</div>
|
|
130
403
|
</div>
|
|
131
|
-
<div class="progress-text" id="text">0%</div>
|
|
132
404
|
<script>
|
|
133
405
|
const { ipcRenderer } = require('electron');
|
|
134
|
-
ipcRenderer.
|
|
135
|
-
document.getElementById('progress').style.width = data.percent + '%';
|
|
136
|
-
document.getElementById('text').textContent =
|
|
137
|
-
data.percent + '% (' + formatBytes(data.transferred) + ' / ' + formatBytes(data.total) + ')';
|
|
138
|
-
});
|
|
139
|
-
function formatBytes(bytes) {
|
|
140
|
-
if (bytes < 1024) return bytes + ' B';
|
|
141
|
-
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
|
142
|
-
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
143
|
-
}
|
|
406
|
+
function close() { ipcRenderer.send('updater-error-close'); }
|
|
144
407
|
</script>
|
|
145
408
|
</body>
|
|
146
409
|
</html>
|
|
147
410
|
`;
|
|
148
|
-
|
|
411
|
+
win.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
412
|
+
electron_1.ipcMain.once('updater-error-close', () => {
|
|
413
|
+
this.closeCurrentWindow();
|
|
414
|
+
});
|
|
149
415
|
}
|
|
150
416
|
updateProgress(progress) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
closeProgressWindow() {
|
|
156
|
-
if (this.progressWindow && !this.progressWindow.isDestroyed()) {
|
|
157
|
-
this.progressWindow.close();
|
|
158
|
-
this.progressWindow = null;
|
|
417
|
+
// Throttle обновлений чтобы проценты не скакали
|
|
418
|
+
this.lastProgress = progress;
|
|
419
|
+
if (this.progressThrottleTimer) {
|
|
420
|
+
return;
|
|
159
421
|
}
|
|
422
|
+
this.progressThrottleTimer = setTimeout(() => {
|
|
423
|
+
this.progressThrottleTimer = null;
|
|
424
|
+
if (this.currentWindow && !this.currentWindow.isDestroyed() && this.lastProgress) {
|
|
425
|
+
this.currentWindow.webContents.send('progress', this.lastProgress);
|
|
426
|
+
}
|
|
427
|
+
}, 100); // Обновляем не чаще чем раз в 100мс
|
|
160
428
|
}
|
|
161
429
|
async checkForUpdates() {
|
|
162
430
|
await this.updater.checkForUpdates();
|
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":";;;AAAA,uCAA0D;AAU1D,MAAa,SAAS;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|
package/dist/updater.d.ts
CHANGED
|
@@ -7,13 +7,39 @@ export declare class Updater extends EventEmitter {
|
|
|
7
7
|
private downloadedFile;
|
|
8
8
|
private checkTimer;
|
|
9
9
|
constructor(config: UpdaterConfig);
|
|
10
|
+
/**
|
|
11
|
+
* Очищает старые временные файлы от предыдущих обновлений
|
|
12
|
+
*/
|
|
13
|
+
private cleanupOldUpdateFiles;
|
|
10
14
|
on<K extends keyof UpdaterEvents>(event: K, listener: UpdaterEvents[K]): this;
|
|
11
15
|
emit<K extends keyof UpdaterEvents>(event: K, ...args: Parameters<UpdaterEvents[K]>): boolean;
|
|
12
16
|
checkForUpdates(): Promise<UpdateInfo>;
|
|
13
17
|
downloadUpdate(): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Получает корневую директорию приложения относительно исполняемого файла
|
|
20
|
+
*/
|
|
21
|
+
private getAppRootPath;
|
|
14
22
|
installUpdate(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Находит корневую папку обновления внутри распакованного архива.
|
|
25
|
+
* Архив может содержать файлы напрямую или в подпапке (win-unpacked, linux-unpacked, etc.)
|
|
26
|
+
*/
|
|
27
|
+
private findUpdateRoot;
|
|
28
|
+
/**
|
|
29
|
+
* Копирует содержимое директории рекурсивно
|
|
30
|
+
*/
|
|
31
|
+
private copyDirectory;
|
|
32
|
+
/**
|
|
33
|
+
* Установка через helper скрипт (Windows/Linux/macOS)
|
|
34
|
+
* Скрипт ждёт завершения приложения, копирует файлы и перезапускает
|
|
35
|
+
*/
|
|
36
|
+
private installWithHelper;
|
|
15
37
|
startAutoCheck(): void;
|
|
16
38
|
stopAutoCheck(): void;
|
|
17
39
|
getUpdateInfo(): UpdateInfo | null;
|
|
40
|
+
/**
|
|
41
|
+
* Отключает autoInstall (используется UI для ручного управления установкой)
|
|
42
|
+
*/
|
|
43
|
+
disableAutoInstall(): void;
|
|
18
44
|
}
|
|
19
45
|
//# sourceMappingURL=updater.d.ts.map
|
package/dist/updater.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,EAIL,UAAU,EACV,aAAa,EACb,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,qBAAa,OAAQ,SAAQ,YAAY;IACvC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,UAAU,CAA+B;gBAErC,MAAM,EAAE,aAAa;IAsBjC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA8B7B,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAI7E,IAAI,CAAC,CAAC,SAAS,MAAM,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;IAIvF,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC;IAmCtC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IA4DvC;;OAEG;IACH,OAAO,CAAC,cAAc;IAchB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA+EpC;;;OAGG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;YACW,aAAa;IAsB3B;;;OAGG;YACW,iBAAiB;IAuG/B,cAAc,IAAI,IAAI;IAQtB,aAAa,IAAI,IAAI;IAOrB,aAAa,IAAI,UAAU,GAAG,IAAI;IAIlC;;OAEG;IACH,kBAAkB,IAAI,IAAI;CAG3B"}
|