ee-core 2.1.1-beta.4 → 2.1.1
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/addon/window/index.js +8 -2
- package/electron/winState.js +186 -0
- package/package.json +1 -3
package/addon/window/index.js
CHANGED
|
@@ -18,6 +18,12 @@ class WinAddon {
|
|
|
18
18
|
* @since 1.0.0
|
|
19
19
|
*/
|
|
20
20
|
create(name, opt) {
|
|
21
|
+
|
|
22
|
+
// todo 判断name是否唯一
|
|
23
|
+
// if (this.windowContentsIdMap.hasOwnProperty(name)) {
|
|
24
|
+
// throw new Error(`[addon] [window] Name: ${name} already exists!`);
|
|
25
|
+
// }
|
|
26
|
+
|
|
21
27
|
const options = Object.assign({
|
|
22
28
|
x: 10,
|
|
23
29
|
y: 10,
|
|
@@ -74,7 +80,7 @@ class WinAddon {
|
|
|
74
80
|
* @function
|
|
75
81
|
* @since 1.0.0
|
|
76
82
|
*/
|
|
77
|
-
registerWCid
|
|
83
|
+
registerWCid(name, id) {
|
|
78
84
|
this.windowContentsIdMap[name] = id;
|
|
79
85
|
}
|
|
80
86
|
|
|
@@ -84,7 +90,7 @@ class WinAddon {
|
|
|
84
90
|
* @function
|
|
85
91
|
* @since 1.0.0
|
|
86
92
|
*/
|
|
87
|
-
removeWCid
|
|
93
|
+
removeWCid(name) {
|
|
88
94
|
delete this.windowContentsIdMap[name];
|
|
89
95
|
}
|
|
90
96
|
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const electron = require('electron');
|
|
5
|
+
const jsonfile = require('jsonfile');
|
|
6
|
+
const mkdirp = require('mkdirp');
|
|
7
|
+
|
|
8
|
+
module.exports = function (options) {
|
|
9
|
+
const app = electron.app || electron.remote.app;
|
|
10
|
+
const screen = electron.screen || electron.remote.screen;
|
|
11
|
+
let state;
|
|
12
|
+
let winRef;
|
|
13
|
+
let stateChangeTimer;
|
|
14
|
+
const eventHandlingDelay = 100;
|
|
15
|
+
const config = Object.assign({
|
|
16
|
+
file: 'window-state.json',
|
|
17
|
+
path: app.getPath('userData'),
|
|
18
|
+
maximize: true,
|
|
19
|
+
fullScreen: true
|
|
20
|
+
}, options);
|
|
21
|
+
const fullStoreFileName = path.join(config.path, config.file);
|
|
22
|
+
|
|
23
|
+
function isNormal(win) {
|
|
24
|
+
return !win.isMaximized() && !win.isMinimized() && !win.isFullScreen();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function hasBounds() {
|
|
28
|
+
return state &&
|
|
29
|
+
Number.isInteger(state.x) &&
|
|
30
|
+
Number.isInteger(state.y) &&
|
|
31
|
+
Number.isInteger(state.width) && state.width > 0 &&
|
|
32
|
+
Number.isInteger(state.height) && state.height > 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resetStateToDefault() {
|
|
36
|
+
const displayBounds = screen.getPrimaryDisplay().bounds;
|
|
37
|
+
|
|
38
|
+
// Reset state to default values on the primary display
|
|
39
|
+
state = {
|
|
40
|
+
width: config.defaultWidth || 800,
|
|
41
|
+
height: config.defaultHeight || 600,
|
|
42
|
+
x: 0,
|
|
43
|
+
y: 0,
|
|
44
|
+
displayBounds
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function windowWithinBounds(bounds) {
|
|
49
|
+
return (
|
|
50
|
+
state.x >= bounds.x &&
|
|
51
|
+
state.y >= bounds.y &&
|
|
52
|
+
state.x + state.width <= bounds.x + bounds.width &&
|
|
53
|
+
state.y + state.height <= bounds.y + bounds.height
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function ensureWindowVisibleOnSomeDisplay() {
|
|
58
|
+
const visible = screen.getAllDisplays().some(display => {
|
|
59
|
+
return windowWithinBounds(display.bounds);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (!visible) {
|
|
63
|
+
// Window is partially or fully not visible now.
|
|
64
|
+
// Reset it to safe defaults.
|
|
65
|
+
return resetStateToDefault();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function validateState() {
|
|
70
|
+
const isValid = state && (hasBounds() || state.isMaximized || state.isFullScreen);
|
|
71
|
+
if (!isValid) {
|
|
72
|
+
state = null;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (hasBounds() && state.displayBounds) {
|
|
77
|
+
ensureWindowVisibleOnSomeDisplay();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function updateState(win) {
|
|
82
|
+
win = win || winRef;
|
|
83
|
+
if (!win) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Don't throw an error when window was closed
|
|
87
|
+
try {
|
|
88
|
+
const winBounds = win.getBounds();
|
|
89
|
+
if (isNormal(win)) {
|
|
90
|
+
state.x = winBounds.x;
|
|
91
|
+
state.y = winBounds.y;
|
|
92
|
+
state.width = winBounds.width;
|
|
93
|
+
state.height = winBounds.height;
|
|
94
|
+
}
|
|
95
|
+
state.isMaximized = win.isMaximized();
|
|
96
|
+
state.isFullScreen = win.isFullScreen();
|
|
97
|
+
state.displayBounds = screen.getDisplayMatching(winBounds).bounds;
|
|
98
|
+
} catch (err) {}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function saveState(win) {
|
|
102
|
+
// Update window state only if it was provided
|
|
103
|
+
if (win) {
|
|
104
|
+
updateState(win);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Save state
|
|
108
|
+
try {
|
|
109
|
+
mkdirp.sync(path.dirname(fullStoreFileName));
|
|
110
|
+
jsonfile.writeFileSync(fullStoreFileName, state);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// Don't care
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function stateChangeHandler() {
|
|
117
|
+
// Handles both 'resize' and 'move'
|
|
118
|
+
clearTimeout(stateChangeTimer);
|
|
119
|
+
stateChangeTimer = setTimeout(updateState, eventHandlingDelay);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function closeHandler() {
|
|
123
|
+
updateState();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function closedHandler() {
|
|
127
|
+
// Unregister listeners and save state
|
|
128
|
+
unmanage();
|
|
129
|
+
saveState();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function manage(win) {
|
|
133
|
+
if (config.maximize && state.isMaximized) {
|
|
134
|
+
win.maximize();
|
|
135
|
+
}
|
|
136
|
+
if (config.fullScreen && state.isFullScreen) {
|
|
137
|
+
win.setFullScreen(true);
|
|
138
|
+
}
|
|
139
|
+
win.on('resize', stateChangeHandler);
|
|
140
|
+
win.on('move', stateChangeHandler);
|
|
141
|
+
win.on('close', closeHandler);
|
|
142
|
+
win.on('closed', closedHandler);
|
|
143
|
+
winRef = win;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function unmanage() {
|
|
147
|
+
if (winRef) {
|
|
148
|
+
winRef.removeListener('resize', stateChangeHandler);
|
|
149
|
+
winRef.removeListener('move', stateChangeHandler);
|
|
150
|
+
clearTimeout(stateChangeTimer);
|
|
151
|
+
winRef.removeListener('close', closeHandler);
|
|
152
|
+
winRef.removeListener('closed', closedHandler);
|
|
153
|
+
winRef = null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Load previous state
|
|
158
|
+
try {
|
|
159
|
+
state = jsonfile.readFileSync(fullStoreFileName);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
// Don't care
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Check state validity
|
|
165
|
+
validateState();
|
|
166
|
+
|
|
167
|
+
// Set state fallback values
|
|
168
|
+
state = Object.assign({
|
|
169
|
+
width: config.defaultWidth || 800,
|
|
170
|
+
height: config.defaultHeight || 600
|
|
171
|
+
}, state);
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
get x() { return state.x; },
|
|
175
|
+
get y() { return state.y; },
|
|
176
|
+
get width() { return state.width; },
|
|
177
|
+
get height() { return state.height; },
|
|
178
|
+
get displayBounds() { return state.displayBounds; },
|
|
179
|
+
get isMaximized() { return state.isMaximized; },
|
|
180
|
+
get isFullScreen() { return state.isFullScreen; },
|
|
181
|
+
saveState,
|
|
182
|
+
unmanage,
|
|
183
|
+
manage,
|
|
184
|
+
resetStateToDefault
|
|
185
|
+
};
|
|
186
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ee-core",
|
|
3
|
-
"version": "2.1.1
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "ee core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"publish-beta": "npm publish --tag beta",
|
|
8
|
-
"publish": "npm publish",
|
|
9
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
10
8
|
},
|
|
11
9
|
"author": "",
|