electron-screenshots 0.5.18 → 0.5.20

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.
@@ -1,448 +1,455 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- var desc = Object.getOwnPropertyDescriptor(m, k);
20
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
- desc = { enumerable: true, get: function() { return m[k]; } };
22
- }
23
- Object.defineProperty(o, k2, desc);
24
- }) : (function(o, m, k, k2) {
25
- if (k2 === undefined) k2 = k;
26
- o[k2] = m[k];
27
- }));
28
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
- Object.defineProperty(o, "default", { enumerable: true, value: v });
30
- }) : function(o, v) {
31
- o["default"] = v;
32
- });
33
- var __importStar = (this && this.__importStar) || function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
- return new (P || (P = Promise))(function (resolve, reject) {
43
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
- step((generator = generator.apply(thisArg, _arguments || [])).next());
47
- });
48
- };
49
- var __generator = (this && this.__generator) || function (thisArg, body) {
50
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
51
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
52
- function verb(n) { return function (v) { return step([n, v]); }; }
53
- function step(op) {
54
- if (f) throw new TypeError("Generator is already executing.");
55
- while (_) try {
56
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
- if (y = 0, t) op = [op[0] & 2, t.value];
58
- switch (op[0]) {
59
- case 0: case 1: t = op; break;
60
- case 4: _.label++; return { value: op[1], done: false };
61
- case 5: _.label++; y = op[1]; op = [0]; continue;
62
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
63
- default:
64
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
65
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
66
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
67
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
68
- if (t[2]) _.ops.pop();
69
- _.trys.pop(); continue;
70
- }
71
- op = body.call(thisArg, _);
72
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
73
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
74
- }
75
- };
76
- var __importDefault = (this && this.__importDefault) || function (mod) {
77
- return (mod && mod.__esModule) ? mod : { "default": mod };
78
- };
79
- Object.defineProperty(exports, "__esModule", { value: true });
80
- var debug_1 = __importDefault(require("debug"));
81
- var electron_1 = require("electron");
82
- var events_1 = __importDefault(require("events"));
83
- var fs_extra_1 = __importDefault(require("fs-extra"));
84
- var event_1 = __importDefault(require("./event"));
85
- var getDisplay_1 = __importDefault(require("./getDisplay"));
86
- var padStart_1 = __importDefault(require("./padStart"));
87
- var Screenshots = /** @class */ (function (_super) {
88
- __extends(Screenshots, _super);
89
- function Screenshots(opts) {
90
- var _this = _super.call(this) || this;
91
- // 截图窗口对象
92
- _this.$win = null;
93
- _this.$view = new electron_1.BrowserView({
94
- webPreferences: {
95
- preload: require.resolve('./preload.js'),
96
- nodeIntegration: false,
97
- contextIsolation: true
98
- }
99
- });
100
- _this.isReady = new Promise(function (resolve) {
101
- electron_1.ipcMain.once('SCREENSHOTS:ready', function () {
102
- _this.logger('SCREENSHOTS:ready');
103
- resolve();
104
- });
105
- });
106
- _this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || (0, debug_1.default)('electron-screenshots');
107
- _this.singleWindow = (opts === null || opts === void 0 ? void 0 : opts.singleWindow) || false;
108
- _this.listenIpc();
109
- _this.$view.webContents.loadURL("file://".concat(require.resolve('react-screenshots/electron/electron.html')));
110
- if (opts === null || opts === void 0 ? void 0 : opts.lang) {
111
- _this.setLang(opts.lang);
112
- }
113
- return _this;
114
- }
115
- /**
116
- * 开始截图
117
- */
118
- Screenshots.prototype.startCapture = function () {
119
- return __awaiter(this, void 0, void 0, function () {
120
- var display, imageUrl;
121
- return __generator(this, function (_a) {
122
- switch (_a.label) {
123
- case 0:
124
- this.logger('startCapture');
125
- display = (0, getDisplay_1.default)();
126
- return [4 /*yield*/, Promise.all([this.capture(display), this.isReady])];
127
- case 1:
128
- imageUrl = (_a.sent())[0];
129
- return [4 /*yield*/, this.createWindow(display)];
130
- case 2:
131
- _a.sent();
132
- this.$view.webContents.send('SCREENSHOTS:capture', display, imageUrl);
133
- return [2 /*return*/];
134
- }
135
- });
136
- });
137
- };
138
- /**
139
- * 结束截图
140
- */
141
- Screenshots.prototype.endCapture = function () {
142
- return __awaiter(this, void 0, void 0, function () {
143
- return __generator(this, function (_a) {
144
- switch (_a.label) {
145
- case 0:
146
- this.logger('endCapture');
147
- return [4 /*yield*/, this.reset()];
148
- case 1:
149
- _a.sent();
150
- if (!this.$win) {
151
- return [2 /*return*/];
152
- }
153
- // 先清除 Kiosk 模式,然后取消全屏才有效
154
- this.$win.setKiosk(false);
155
- this.$win.setSimpleFullScreen(false);
156
- this.$win.blur();
157
- this.$win.blurWebView();
158
- this.$win.unmaximize();
159
- this.$win.removeBrowserView(this.$view);
160
- if (this.singleWindow) {
161
- this.$win.hide();
162
- }
163
- else {
164
- this.$win.destroy();
165
- }
166
- return [2 /*return*/];
167
- }
168
- });
169
- });
170
- };
171
- /**
172
- * 设置语言
173
- */
174
- Screenshots.prototype.setLang = function (lang) {
175
- return __awaiter(this, void 0, void 0, function () {
176
- return __generator(this, function (_a) {
177
- switch (_a.label) {
178
- case 0:
179
- this.logger('setLang', lang);
180
- return [4 /*yield*/, this.isReady];
181
- case 1:
182
- _a.sent();
183
- this.$view.webContents.send('SCREENSHOTS:setLang', lang);
184
- return [2 /*return*/];
185
- }
186
- });
187
- });
188
- };
189
- Screenshots.prototype.reset = function () {
190
- return __awaiter(this, void 0, void 0, function () {
191
- return __generator(this, function (_a) {
192
- switch (_a.label) {
193
- case 0:
194
- // 重置截图区域
195
- this.$view.webContents.send('SCREENSHOTS:reset');
196
- // 保证 UI 有足够的时间渲染
197
- return [4 /*yield*/, Promise.race([
198
- new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 500); }),
199
- new Promise(function (resolve) { return electron_1.ipcMain.once('SCREENSHOTS:reset', function () { return resolve(); }); })
200
- ])];
201
- case 1:
202
- // 保证 UI 有足够的时间渲染
203
- _a.sent();
204
- return [2 /*return*/];
205
- }
206
- });
207
- });
208
- };
209
- /**
210
- * 初始化窗口
211
- */
212
- Screenshots.prototype.createWindow = function (display) {
213
- var _a, _b;
214
- return __awaiter(this, void 0, void 0, function () {
215
- var _this = this;
216
- return __generator(this, function (_c) {
217
- switch (_c.label) {
218
- case 0:
219
- // 重置截图区域
220
- return [4 /*yield*/, this.reset()
221
- // 复用未销毁的窗口
222
- ];
223
- case 1:
224
- // 重置截图区域
225
- _c.sent();
226
- // 复用未销毁的窗口
227
- if (!this.$win || ((_b = (_a = this.$win) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
228
- this.$win = new electron_1.BrowserWindow({
229
- title: 'screenshots',
230
- x: display.x,
231
- y: display.y,
232
- width: display.width,
233
- height: display.height,
234
- useContentSize: true,
235
- frame: false,
236
- show: false,
237
- autoHideMenuBar: true,
238
- transparent: true,
239
- // mac resizable 设置为 false 会导致页面崩溃
240
- resizable: process.platform !== 'darwin',
241
- movable: false,
242
- // focusable: true, 否则窗口不能及时响应esc按键,输入框也不能输入
243
- focusable: true,
244
- /**
245
- * linux 下必须设置为false,否则不能全屏显示在最上层
246
- * mac 下设置为false,否则可能会导致程序坞不恢复问题
247
- * https://github.com/nashaofu/screenshots/issues/148
248
- */
249
- // fullscreen: process.platform === 'darwin',
250
- // 设为true 防止mac新开一个桌面,影响效果
251
- simpleFullscreen: process.platform === 'darwin',
252
- backgroundColor: '#00000000',
253
- titleBarStyle: 'hidden',
254
- alwaysOnTop: true,
255
- enableLargerThanScreen: true,
256
- skipTaskbar: true,
257
- hasShadow: false,
258
- paintWhenInitiallyHidden: false,
259
- acceptFirstMouse: true
260
- });
261
- this.$win.on('show', function () {
262
- var _a, _b;
263
- (_a = _this.$win) === null || _a === void 0 ? void 0 : _a.focus();
264
- /**
265
- * 在窗口显示时设置,防止与 fullscreen、x、y、width、height 等冲突, 导致显示效果不符合预期
266
- * mac 下不设置 kiosk 模式,https://github.com/nashaofu/screenshots/issues/148
267
- */
268
- (_b = _this.$win) === null || _b === void 0 ? void 0 : _b.setKiosk(process.platform !== 'darwin');
269
- });
270
- this.$win.on('closed', function () {
271
- _this.$win = null;
272
- });
273
- }
274
- this.$win.setBrowserView(this.$view);
275
- // 适定平台
276
- if (process.platform === 'darwin') {
277
- this.$win.setWindowButtonVisibility(false);
278
- }
279
- if (process.platform !== 'win32') {
280
- this.$win.setVisibleOnAllWorkspaces(true, {
281
- visibleOnFullScreen: true,
282
- skipTransformProcessType: true
283
- });
284
- }
285
- this.$win.blur();
286
- this.$win.setKiosk(false);
287
- if (process.platform === 'darwin') {
288
- this.$win.setSimpleFullScreen(true);
289
- }
290
- this.$win.setBounds(display);
291
- this.$view.setBounds({
292
- x: 0,
293
- y: 0,
294
- width: display.width,
295
- height: display.height
296
- });
297
- this.$win.setAlwaysOnTop(true);
298
- this.$win.show();
299
- return [2 /*return*/];
300
- }
301
- });
302
- });
303
- };
304
- Screenshots.prototype.capture = function (display) {
305
- return __awaiter(this, void 0, void 0, function () {
306
- var NodeScreenshots, capturer, image, err_1, sources, source;
307
- return __generator(this, function (_a) {
308
- switch (_a.label) {
309
- case 0:
310
- this.logger('SCREENSHOTS:capture');
311
- _a.label = 1;
312
- case 1:
313
- _a.trys.push([1, 4, , 6]);
314
- return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require('node-screenshots')); })];
315
- case 2:
316
- NodeScreenshots = (_a.sent()).Screenshots;
317
- capturer = NodeScreenshots.fromPoint(display.x + display.width / 2, display.y + display.height / 2);
318
- this.logger('SCREENSHOTS:capture NodeScreenshots.fromPoint arguments %o', display);
319
- this.logger('SCREENSHOTS:capture NodeScreenshots.fromPoint return %o', capturer
320
- ? {
321
- id: capturer.id,
322
- x: capturer.x,
323
- y: capturer.y,
324
- width: capturer.width,
325
- height: capturer.height,
326
- rotation: capturer.rotation,
327
- scaleFactor: capturer.scaleFactor,
328
- isPrimary: capturer.isPrimary
329
- }
330
- : null);
331
- if (!capturer) {
332
- throw new Error("NodeScreenshots.fromDisplay(".concat(display.id, ") get null"));
333
- }
334
- return [4 /*yield*/, capturer.capture()];
335
- case 3:
336
- image = _a.sent();
337
- return [2 /*return*/, "data:image/png;base64,".concat(image.toString('base64'))];
338
- case 4:
339
- err_1 = _a.sent();
340
- this.logger('SCREENSHOTS:capture NodeScreenshots capture() error %o', err_1);
341
- return [4 /*yield*/, electron_1.desktopCapturer.getSources({
342
- types: ['screen'],
343
- thumbnailSize: {
344
- width: display.width * display.scaleFactor,
345
- height: display.height * display.scaleFactor
346
- }
347
- })];
348
- case 5:
349
- sources = _a.sent();
350
- source = void 0;
351
- // Linux系统上,screen.getDisplayNearestPoint 返回的 Display 对象的 id
352
- // 和这里 source 对象上的 display_id(Linux上,这个值是空字符串) 或 id 的中间部分,都不一致
353
- // 但是,如果只有一个显示器的话,其实不用判断,直接返回就行
354
- if (sources.length === 1) {
355
- source = sources[0];
356
- }
357
- else {
358
- source = sources.find(function (source) {
359
- return source.display_id === display.id.toString() || source.id.startsWith("screen:".concat(display.id, ":"));
360
- });
361
- }
362
- if (!source) {
363
- this.logger("SCREENSHOTS:capture Can't find screen source. sources: %o, display: %o", sources, display);
364
- throw new Error("Can't find screen source");
365
- }
366
- return [2 /*return*/, source.thumbnail.toDataURL()];
367
- case 6: return [2 /*return*/];
368
- }
369
- });
370
- });
371
- };
372
- /**
373
- * 绑定ipc时间处理
374
- */
375
- Screenshots.prototype.listenIpc = function () {
376
- var _this = this;
377
- /**
378
- * OK事件
379
- */
380
- electron_1.ipcMain.on('SCREENSHOTS:ok', function (e, buffer, data) {
381
- _this.logger('SCREENSHOTS:ok buffer.length %d, data: %o', buffer.length, data);
382
- var event = new event_1.default();
383
- _this.emit('ok', event, buffer, data);
384
- if (event.defaultPrevented) {
385
- return;
386
- }
387
- electron_1.clipboard.writeImage(electron_1.nativeImage.createFromBuffer(buffer));
388
- _this.endCapture();
389
- });
390
- /**
391
- * CANCEL事件
392
- */
393
- electron_1.ipcMain.on('SCREENSHOTS:cancel', function () {
394
- _this.logger('SCREENSHOTS:cancel');
395
- var event = new event_1.default();
396
- _this.emit('cancel', event);
397
- if (event.defaultPrevented) {
398
- return;
399
- }
400
- _this.endCapture();
401
- });
402
- /**
403
- * SAVE事件
404
- */
405
- electron_1.ipcMain.on('SCREENSHOTS:save', function (e, buffer, data) { return __awaiter(_this, void 0, void 0, function () {
406
- var event, time, year, month, date, hours, minutes, seconds, milliseconds, _a, canceled, filePath;
407
- return __generator(this, function (_b) {
408
- switch (_b.label) {
409
- case 0:
410
- this.logger('SCREENSHOTS:save buffer.length %d, data: %o', buffer.length, data);
411
- event = new event_1.default();
412
- this.emit('save', event, buffer, data);
413
- if (event.defaultPrevented || !this.$win) {
414
- return [2 /*return*/];
415
- }
416
- time = new Date();
417
- year = time.getFullYear();
418
- month = (0, padStart_1.default)(time.getMonth() + 1, 2, '0');
419
- date = (0, padStart_1.default)(time.getDate(), 2, '0');
420
- hours = (0, padStart_1.default)(time.getHours(), 2, '0');
421
- minutes = (0, padStart_1.default)(time.getMinutes(), 2, '0');
422
- seconds = (0, padStart_1.default)(time.getSeconds(), 2, '0');
423
- milliseconds = (0, padStart_1.default)(time.getMilliseconds(), 3, '0');
424
- this.$win.setAlwaysOnTop(false);
425
- return [4 /*yield*/, electron_1.dialog.showSaveDialog(this.$win, {
426
- defaultPath: "".concat(year).concat(month).concat(date).concat(hours).concat(minutes).concat(seconds).concat(milliseconds, ".png")
427
- })];
428
- case 1:
429
- _a = _b.sent(), canceled = _a.canceled, filePath = _a.filePath;
430
- if (!this.$win) {
431
- return [2 /*return*/];
432
- }
433
- this.$win.setAlwaysOnTop(true);
434
- if (canceled || !filePath) {
435
- return [2 /*return*/];
436
- }
437
- return [4 /*yield*/, fs_extra_1.default.writeFile(filePath, buffer)];
438
- case 2:
439
- _b.sent();
440
- this.endCapture();
441
- return [2 /*return*/];
442
- }
443
- });
444
- }); });
445
- };
446
- return Screenshots;
447
- }(events_1.default));
448
- exports.default = Screenshots;
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
+ return new (P || (P = Promise))(function (resolve, reject) {
43
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
47
+ });
48
+ };
49
+ var __generator = (this && this.__generator) || function (thisArg, body) {
50
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
51
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
52
+ function verb(n) { return function (v) { return step([n, v]); }; }
53
+ function step(op) {
54
+ if (f) throw new TypeError("Generator is already executing.");
55
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
56
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
+ if (y = 0, t) op = [op[0] & 2, t.value];
58
+ switch (op[0]) {
59
+ case 0: case 1: t = op; break;
60
+ case 4: _.label++; return { value: op[1], done: false };
61
+ case 5: _.label++; y = op[1]; op = [0]; continue;
62
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
63
+ default:
64
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
65
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
66
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
67
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
68
+ if (t[2]) _.ops.pop();
69
+ _.trys.pop(); continue;
70
+ }
71
+ op = body.call(thisArg, _);
72
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
73
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
74
+ }
75
+ };
76
+ var __importDefault = (this && this.__importDefault) || function (mod) {
77
+ return (mod && mod.__esModule) ? mod : { "default": mod };
78
+ };
79
+ Object.defineProperty(exports, "__esModule", { value: true });
80
+ var debug_1 = __importDefault(require("debug"));
81
+ var electron_1 = require("electron");
82
+ var events_1 = __importDefault(require("events"));
83
+ var fs_extra_1 = __importDefault(require("fs-extra"));
84
+ var event_1 = __importDefault(require("./event"));
85
+ var getDisplay_1 = __importDefault(require("./getDisplay"));
86
+ var padStart_1 = __importDefault(require("./padStart"));
87
+ var Screenshots = /** @class */ (function (_super) {
88
+ __extends(Screenshots, _super);
89
+ function Screenshots(opts) {
90
+ var _this = _super.call(this) || this;
91
+ // 截图窗口对象
92
+ _this.$win = null;
93
+ _this.$view = new electron_1.BrowserView({
94
+ webPreferences: {
95
+ preload: require.resolve('./preload.js'),
96
+ nodeIntegration: false,
97
+ contextIsolation: true,
98
+ },
99
+ });
100
+ _this.isReady = new Promise(function (resolve) {
101
+ electron_1.ipcMain.once('SCREENSHOTS:ready', function () {
102
+ _this.logger('SCREENSHOTS:ready');
103
+ resolve();
104
+ });
105
+ });
106
+ _this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || (0, debug_1.default)('electron-screenshots');
107
+ _this.singleWindow = (opts === null || opts === void 0 ? void 0 : opts.singleWindow) || false;
108
+ _this.listenIpc();
109
+ _this.$view.webContents.loadURL("file://".concat(require.resolve('react-screenshots/electron/electron.html')));
110
+ if (opts === null || opts === void 0 ? void 0 : opts.lang) {
111
+ _this.setLang(opts.lang);
112
+ }
113
+ return _this;
114
+ }
115
+ /**
116
+ * 开始截图
117
+ */
118
+ Screenshots.prototype.startCapture = function () {
119
+ return __awaiter(this, void 0, void 0, function () {
120
+ var display, imageUrl;
121
+ return __generator(this, function (_a) {
122
+ switch (_a.label) {
123
+ case 0:
124
+ this.logger('startCapture');
125
+ display = (0, getDisplay_1.default)();
126
+ return [4 /*yield*/, Promise.all([this.capture(display), this.isReady])];
127
+ case 1:
128
+ imageUrl = (_a.sent())[0];
129
+ return [4 /*yield*/, this.createWindow(display)];
130
+ case 2:
131
+ _a.sent();
132
+ this.$view.webContents.send('SCREENSHOTS:capture', display, imageUrl);
133
+ return [2 /*return*/];
134
+ }
135
+ });
136
+ });
137
+ };
138
+ /**
139
+ * 结束截图
140
+ */
141
+ Screenshots.prototype.endCapture = function () {
142
+ return __awaiter(this, void 0, void 0, function () {
143
+ return __generator(this, function (_a) {
144
+ switch (_a.label) {
145
+ case 0:
146
+ this.logger('endCapture');
147
+ return [4 /*yield*/, this.reset()];
148
+ case 1:
149
+ _a.sent();
150
+ if (!this.$win) {
151
+ return [2 /*return*/];
152
+ }
153
+ // 先清除 Kiosk 模式,然后取消全屏才有效
154
+ this.$win.setKiosk(false);
155
+ this.$win.setSimpleFullScreen(false);
156
+ this.$win.blur();
157
+ this.$win.blurWebView();
158
+ this.$win.unmaximize();
159
+ this.$win.removeBrowserView(this.$view);
160
+ if (this.singleWindow) {
161
+ this.$win.hide();
162
+ }
163
+ else {
164
+ this.$win.destroy();
165
+ }
166
+ return [2 /*return*/];
167
+ }
168
+ });
169
+ });
170
+ };
171
+ /**
172
+ * 设置语言
173
+ */
174
+ Screenshots.prototype.setLang = function (lang) {
175
+ return __awaiter(this, void 0, void 0, function () {
176
+ return __generator(this, function (_a) {
177
+ switch (_a.label) {
178
+ case 0:
179
+ this.logger('setLang', lang);
180
+ return [4 /*yield*/, this.isReady];
181
+ case 1:
182
+ _a.sent();
183
+ this.$view.webContents.send('SCREENSHOTS:setLang', lang);
184
+ return [2 /*return*/];
185
+ }
186
+ });
187
+ });
188
+ };
189
+ Screenshots.prototype.reset = function () {
190
+ return __awaiter(this, void 0, void 0, function () {
191
+ return __generator(this, function (_a) {
192
+ switch (_a.label) {
193
+ case 0:
194
+ // 重置截图区域
195
+ this.$view.webContents.send('SCREENSHOTS:reset');
196
+ // 保证 UI 有足够的时间渲染
197
+ return [4 /*yield*/, Promise.race([
198
+ new Promise(function (resolve) {
199
+ setTimeout(function () { return resolve(); }, 500);
200
+ }),
201
+ new Promise(function (resolve) {
202
+ electron_1.ipcMain.once('SCREENSHOTS:reset', function () { return resolve(); });
203
+ }),
204
+ ])];
205
+ case 1:
206
+ // 保证 UI 有足够的时间渲染
207
+ _a.sent();
208
+ return [2 /*return*/];
209
+ }
210
+ });
211
+ });
212
+ };
213
+ /**
214
+ * 初始化窗口
215
+ */
216
+ Screenshots.prototype.createWindow = function (display) {
217
+ var _a, _b;
218
+ return __awaiter(this, void 0, void 0, function () {
219
+ var _this = this;
220
+ return __generator(this, function (_c) {
221
+ switch (_c.label) {
222
+ case 0:
223
+ // 重置截图区域
224
+ return [4 /*yield*/, this.reset()];
225
+ case 1:
226
+ // 重置截图区域
227
+ _c.sent();
228
+ // 复用未销毁的窗口
229
+ if (!this.$win || ((_b = (_a = this.$win) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
230
+ this.$win = new electron_1.BrowserWindow({
231
+ title: 'screenshots',
232
+ x: display.x,
233
+ y: display.y,
234
+ width: display.width,
235
+ height: display.height,
236
+ useContentSize: true,
237
+ frame: false,
238
+ show: false,
239
+ autoHideMenuBar: true,
240
+ transparent: true,
241
+ // mac resizable 设置为 true 会导致应用崩溃
242
+ resizable: process.platform !== 'darwin',
243
+ movable: false,
244
+ // focusable 必须设置为 true, 否则窗口不能及时响应esc按键,输入框也不能输入
245
+ focusable: true,
246
+ // mac fullscreenable 设置为 true 会导致应用崩溃
247
+ fullscreenable: process.platform !== 'darwin',
248
+ /**
249
+ * linux 下必须设置为false,否则不能全屏显示在最上层
250
+ * mac 下设置为false,否则可能会导致程序坞不恢复问题
251
+ * https://github.com/nashaofu/screenshots/issues/148
252
+ */
253
+ // fullscreen: process.platform === 'darwin',
254
+ // 设为true 防止mac新开一个桌面,影响效果
255
+ simpleFullscreen: process.platform === 'darwin',
256
+ backgroundColor: '#00000000',
257
+ titleBarStyle: 'hidden',
258
+ alwaysOnTop: true,
259
+ enableLargerThanScreen: true,
260
+ skipTaskbar: true,
261
+ hasShadow: false,
262
+ paintWhenInitiallyHidden: false,
263
+ acceptFirstMouse: true,
264
+ });
265
+ this.$win.on('show', function () {
266
+ var _a, _b;
267
+ (_a = _this.$win) === null || _a === void 0 ? void 0 : _a.focus();
268
+ /**
269
+ * 在窗口显示时设置,防止与 fullscreen、x、y、width、height 等冲突, 导致显示效果不符合预期
270
+ * mac 下不设置 kiosk 模式,https://github.com/nashaofu/screenshots/issues/148
271
+ */
272
+ (_b = _this.$win) === null || _b === void 0 ? void 0 : _b.setKiosk(process.platform !== 'darwin');
273
+ });
274
+ this.$win.on('closed', function () {
275
+ _this.$win = null;
276
+ });
277
+ }
278
+ this.$win.setBrowserView(this.$view);
279
+ // 适定平台
280
+ if (process.platform === 'darwin') {
281
+ this.$win.setWindowButtonVisibility(false);
282
+ }
283
+ if (process.platform !== 'win32') {
284
+ this.$win.setVisibleOnAllWorkspaces(true, {
285
+ visibleOnFullScreen: true,
286
+ skipTransformProcessType: true,
287
+ });
288
+ }
289
+ this.$win.blur();
290
+ this.$win.setKiosk(false);
291
+ if (process.platform === 'darwin') {
292
+ this.$win.setSimpleFullScreen(true);
293
+ }
294
+ this.$win.setBounds(display);
295
+ this.$view.setBounds({
296
+ x: 0,
297
+ y: 0,
298
+ width: display.width,
299
+ height: display.height,
300
+ });
301
+ this.$win.setAlwaysOnTop(true);
302
+ this.$win.show();
303
+ return [2 /*return*/];
304
+ }
305
+ });
306
+ });
307
+ };
308
+ Screenshots.prototype.capture = function (display) {
309
+ return __awaiter(this, void 0, void 0, function () {
310
+ var NodeScreenshots, capturer, image, err_1, sources, source;
311
+ return __generator(this, function (_a) {
312
+ switch (_a.label) {
313
+ case 0:
314
+ this.logger('SCREENSHOTS:capture');
315
+ _a.label = 1;
316
+ case 1:
317
+ _a.trys.push([1, 4, , 6]);
318
+ return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require('node-screenshots')); })];
319
+ case 2:
320
+ NodeScreenshots = (_a.sent()).Screenshots;
321
+ capturer = NodeScreenshots.fromPoint(display.x + display.width / 2, display.y + display.height / 2);
322
+ this.logger('SCREENSHOTS:capture NodeScreenshots.fromPoint arguments %o', display);
323
+ this.logger('SCREENSHOTS:capture NodeScreenshots.fromPoint return %o', capturer
324
+ ? {
325
+ id: capturer.id,
326
+ x: capturer.x,
327
+ y: capturer.y,
328
+ width: capturer.width,
329
+ height: capturer.height,
330
+ rotation: capturer.rotation,
331
+ scaleFactor: capturer.scaleFactor,
332
+ isPrimary: capturer.isPrimary,
333
+ }
334
+ : null);
335
+ if (!capturer) {
336
+ throw new Error("NodeScreenshots.fromDisplay(".concat(display.id, ") get null"));
337
+ }
338
+ return [4 /*yield*/, capturer.capture()];
339
+ case 3:
340
+ image = _a.sent();
341
+ return [2 /*return*/, "data:image/png;base64,".concat(image.toString('base64'))];
342
+ case 4:
343
+ err_1 = _a.sent();
344
+ this.logger('SCREENSHOTS:capture NodeScreenshots capture() error %o', err_1);
345
+ return [4 /*yield*/, electron_1.desktopCapturer.getSources({
346
+ types: ['screen'],
347
+ thumbnailSize: {
348
+ width: display.width * display.scaleFactor,
349
+ height: display.height * display.scaleFactor,
350
+ },
351
+ })];
352
+ case 5:
353
+ sources = _a.sent();
354
+ source = void 0;
355
+ // Linux系统上,screen.getDisplayNearestPoint 返回的 Display 对象的 id
356
+ // 和这里 source 对象上的 display_id(Linux上,这个值是空字符串) 或 id 的中间部分,都不一致
357
+ // 但是,如果只有一个显示器的话,其实不用判断,直接返回就行
358
+ if (sources.length === 1) {
359
+ source = sources[0];
360
+ }
361
+ else {
362
+ source = sources.find(function (item) { return item.display_id === display.id.toString()
363
+ || item.id.startsWith("screen:".concat(display.id, ":")); });
364
+ }
365
+ if (!source) {
366
+ this.logger("SCREENSHOTS:capture Can't find screen source. sources: %o, display: %o", sources, display);
367
+ throw new Error("Can't find screen source");
368
+ }
369
+ return [2 /*return*/, source.thumbnail.toDataURL()];
370
+ case 6: return [2 /*return*/];
371
+ }
372
+ });
373
+ });
374
+ };
375
+ /**
376
+ * 绑定ipc时间处理
377
+ */
378
+ Screenshots.prototype.listenIpc = function () {
379
+ var _this = this;
380
+ /**
381
+ * OK事件
382
+ */
383
+ electron_1.ipcMain.on('SCREENSHOTS:ok', function (e, buffer, data) {
384
+ _this.logger('SCREENSHOTS:ok buffer.length %d, data: %o', buffer.length, data);
385
+ var event = new event_1.default();
386
+ _this.emit('ok', event, buffer, data);
387
+ if (event.defaultPrevented) {
388
+ return;
389
+ }
390
+ electron_1.clipboard.writeImage(electron_1.nativeImage.createFromBuffer(buffer));
391
+ _this.endCapture();
392
+ });
393
+ /**
394
+ * CANCEL事件
395
+ */
396
+ electron_1.ipcMain.on('SCREENSHOTS:cancel', function () {
397
+ _this.logger('SCREENSHOTS:cancel');
398
+ var event = new event_1.default();
399
+ _this.emit('cancel', event);
400
+ if (event.defaultPrevented) {
401
+ return;
402
+ }
403
+ _this.endCapture();
404
+ });
405
+ /**
406
+ * SAVE事件
407
+ */
408
+ electron_1.ipcMain.on('SCREENSHOTS:save', function (e, buffer, data) { return __awaiter(_this, void 0, void 0, function () {
409
+ var event, time, year, month, date, hours, minutes, seconds, milliseconds, _a, canceled, filePath;
410
+ return __generator(this, function (_b) {
411
+ switch (_b.label) {
412
+ case 0:
413
+ this.logger('SCREENSHOTS:save buffer.length %d, data: %o', buffer.length, data);
414
+ event = new event_1.default();
415
+ this.emit('save', event, buffer, data);
416
+ if (event.defaultPrevented || !this.$win) {
417
+ return [2 /*return*/];
418
+ }
419
+ time = new Date();
420
+ year = time.getFullYear();
421
+ month = (0, padStart_1.default)(time.getMonth() + 1, 2, '0');
422
+ date = (0, padStart_1.default)(time.getDate(), 2, '0');
423
+ hours = (0, padStart_1.default)(time.getHours(), 2, '0');
424
+ minutes = (0, padStart_1.default)(time.getMinutes(), 2, '0');
425
+ seconds = (0, padStart_1.default)(time.getSeconds(), 2, '0');
426
+ milliseconds = (0, padStart_1.default)(time.getMilliseconds(), 3, '0');
427
+ this.$win.setAlwaysOnTop(false);
428
+ return [4 /*yield*/, electron_1.dialog.showSaveDialog(this.$win, {
429
+ defaultPath: "".concat(year).concat(month).concat(date).concat(hours).concat(minutes).concat(seconds).concat(milliseconds, ".png"),
430
+ filters: [
431
+ { name: 'Image (png)', extensions: ['png'] },
432
+ { name: 'All Files', extensions: ['*'] },
433
+ ],
434
+ })];
435
+ case 1:
436
+ _a = _b.sent(), canceled = _a.canceled, filePath = _a.filePath;
437
+ if (!this.$win) {
438
+ return [2 /*return*/];
439
+ }
440
+ this.$win.setAlwaysOnTop(true);
441
+ if (canceled || !filePath) {
442
+ return [2 /*return*/];
443
+ }
444
+ return [4 /*yield*/, fs_extra_1.default.writeFile(filePath, buffer)];
445
+ case 2:
446
+ _b.sent();
447
+ this.endCapture();
448
+ return [2 /*return*/];
449
+ }
450
+ });
451
+ }); });
452
+ };
453
+ return Screenshots;
454
+ }(events_1.default));
455
+ exports.default = Screenshots;