Skip to content

Commit 4858f76

Browse files
authored
Merge pull request #49 from nlpsuge/dev-load-sessions-asynchronously
1.Performance improvement: Save and load sessions asynchronously 2.Improve `Restore applications interval`
2 parents b8618c8 + 0da4e81 commit 4858f76

9 files changed

Lines changed: 290 additions & 134 deletions

indicator.js

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ class AwsIndicator extends PanelMenu.Button {
243243
this.menu.addMenuItem(this._searchSessionItem, this._itemIndex++);
244244

245245
this._addScrollableSessionsMenuSection();
246-
this._addSessionItems();
246+
this._addSessionItems().catch((error => {
247+
this._log.error(error, 'Error adding session items while creating indicator menu');
248+
}));
247249

248250
this._addSessionFolderMonitor();
249251
}
@@ -270,31 +272,17 @@ class AwsIndicator extends PanelMenu.Button {
270272

271273
}
272274

273-
_addSessionItems() {
275+
async _addSessionItems() {
274276
if (!GLib.file_test(this._sessions_path, GLib.FileTest.EXISTS)) {
275277
// TODO Empty session
276278
this._log.info(`${this._sessions_path} not found! It's harmless, please save some windows in the panel menu to create it automatically.`);
277279
return;
278280
}
279281

280282
this._log.debug('List all sessions to add session items');
281-
282-
// Recently Closed Session always on the top
283-
const recently_closed_session_file = Gio.File.new_for_path(FileUtils.recently_closed_session_path);
284-
let info = null;
285-
try {
286-
info = recently_closed_session_file.query_info(
287-
[Gio.FILE_ATTRIBUTE_STANDARD_NAME,
288-
Gio.FILE_ATTRIBUTE_TIME_MODIFIED].join(','),
289-
Gio.FileQueryInfoFlags.NONE,
290-
null);
291-
} catch (ignored) {}
292283

293-
let item = new SessionItem.SessionItem(info, recently_closed_session_file, this);
294-
this._sessionsMenuSection.addMenuItem(item, this._itemIndex++);
295-
296284
let sessionFileInfos = [];
297-
FileUtils.listAllSessions(null, false, this._prefsUtils.isDebug(),(file, info) => {
285+
await FileUtils.listAllSessions(null, false, this._prefsUtils.isDebug(),(file, info) => {
298286
// We have an interest in regular and text files
299287

300288
const file_type = info.get_file_type();
@@ -309,27 +297,17 @@ class AwsIndicator extends PanelMenu.Button {
309297
}
310298

311299
// Skip the `Recently Closed Session` file since it has been added to the session list already.
312-
if (file.equal(recently_closed_session_file)) {
300+
if (file.equal(FileUtils.recently_closed_session_file)) {
313301
return;
314302
}
315303

316-
let parent = file.get_parent();
317-
let parentPath;
318-
// https://gjs-docs.gnome.org/gio20~2.66p/gio.file#method-get_parent
319-
// If the this represents the root directory of the file system, then null will be returned.
320-
if (parent === null) {
321-
// Impossible, who puts sessions under the /?
322-
parentPath = '/';
323-
} else {
324-
parentPath = parent.get_path();
325-
}
326-
this._log.debug(`Processing ${file.get_path()} under ${parentPath}`);
304+
this._log.debug(`Processing ${file.get_path()}`);
327305
sessionFileInfos.push({
328306
info: info,
329307
file: file
330308
});
331309

332-
});
310+
}).catch(e => {this._log.error(e, 'Error listing all sessions')});
333311

334312
// Sort by modification time: https://gjs-docs.gnome.org/gio20~2.66p/gio.fileenumerator
335313
// The latest on the top, if a file has no modification time put it on the bottom
@@ -356,6 +334,21 @@ class AwsIndicator extends PanelMenu.Button {
356334
return modification_date_time2.compare(modification_date_time1);
357335
});
358336

337+
this._sessionsMenuSection.removeAll();
338+
339+
let info = null;
340+
try {
341+
info = FileUtils.recently_closed_session_file.query_info(
342+
[Gio.FILE_ATTRIBUTE_STANDARD_NAME,
343+
Gio.FILE_ATTRIBUTE_TIME_MODIFIED].join(','),
344+
Gio.FileQueryInfoFlags.NONE,
345+
null);
346+
} catch (ignored) {}
347+
348+
// Recently Closed Session always on the top
349+
let item = new SessionItem.SessionItem(info, FileUtils.recently_closed_session_file, this);
350+
this._sessionsMenuSection.addMenuItem(item, this._itemIndex++);
351+
359352
for (const sessionFileInfo of sessionFileInfos) {
360353
const info = sessionFileInfo.info;
361354
const file = sessionFileInfo.file;
@@ -373,22 +366,54 @@ class AwsIndicator extends PanelMenu.Button {
373366
const sessionPathFile = Gio.File.new_for_path(this._sessions_path);
374367
// Ok, it's the directory we are monitoring :)
375368
// TODO If the parent of this._sessions_path was deleted, this.monitor don't get the 'changed' signal, so the panel menu items not removed.
376-
this.monitor = sessionPathFile.monitor_directory(Gio.FileMonitorFlags.WATCH_MOUNTS | Gio.FileMonitorFlags.WATCH_MOVES, null);
377-
this.monitor.connect('changed', this._sessionPathChanged.bind(this));
369+
this.monitor = sessionPathFile.monitor_directory(Gio.FileMonitorFlags.NONE, null);
370+
this.monitor.connect('changed', this._sessionChanged.bind(this));
378371
}
379372

380373
// https://gjs-docs.gnome.org/gio20~2.66p/gio.filemonitor#signal-changed
381374
// Looks like the document is wrong ...
382-
_sessionPathChanged(monitor, srcFile, descFile) {
383-
this._log.debug(`Session path changed, readd all session items from ${this._sessions_path}. ${srcFile.get_path()} was changed.`);
384-
this._sessionsMenuSection.removeAll();
375+
_sessionChanged(monitor, file, other_file, eventType) {
376+
this._log.debug(`Session changed, readd all session items from ${this._sessions_path}. ${file.get_path()} changed. Event type: ${eventType}`);
377+
378+
// Ignore CHANGED and CREATED events, since in both cases
379+
// we'll get a CHANGES_DONE_HINT event when done.
380+
if (eventType === Gio.FileMonitorEvent.CHANGED ||
381+
eventType === Gio.FileMonitorEvent.CREATED)
382+
return;
383+
384+
// Ignore temporary files generated by Gio
385+
if (file.get_basename().startsWith('.goutputstream-')) {
386+
return;
387+
}
388+
389+
let info = null;
390+
try {
391+
info = file.query_info(
392+
[Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
393+
Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE].join(','),
394+
Gio.FileQueryInfoFlags.NONE,
395+
null);
396+
} catch (ignored) {}
397+
398+
// Ignore none regular and text files
399+
if (info) {
400+
const file_type = info.get_file_type();
401+
const content_type = info.get_content_type();
402+
if (!(file_type === Gio.FileType.REGULAR &&
403+
content_type === 'text/plain')) {
404+
return;
405+
}
406+
}
407+
385408
// It probably is a problem when there are large amount session files,
386409
// say thousands of them, but who creates that much?
387410
//
388411
// Can use Gio.FileMonitorEvent to modify the results
389412
// of this._sessionsMenuSection._getMenuItems() when the performance
390413
// is a problem to be resolved, it's a more complex implement.
391-
this._addSessionItems();
414+
this._addSessionItems().catch((error => {
415+
this._log.error(error, 'Error adding session items while session was changed');
416+
}));
392417
}
393418

394419
_onAutoRestoreSwitchChanged() {

metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
],
1010
"url": "https://github.com/nlpsuge/gnome-shell-extension-another-window-session-manager",
1111
"uuid": "another-window-session-manager@gmail.com",
12-
"version": 20
12+
"version": 21
1313
}

openWindowsInfoTracker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ var OpenWindowsInfoTracker = class {
5555
// If `error` is not `null` it will be an Error object indicating the
5656
// failure, and `proxy` will be `null` in this case.
5757
if (error !== null) {
58-
this._log.error(error);
58+
this._log.error(new Error(error), 'Failed to create the EndSessionDialog dbus proxy!');
5959
return;
6060
}
6161

prefsCloseWindow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ const RuleRow = GObject.registerClass({
440440
if (previousAcceleratorButton) {
441441
order = previousAcceleratorButton._rule.order + 1
442442
} else {
443-
// The vert first accelerator...
443+
// The very first accelerator...
444444
order = 1;
445445
}
446446

restoreSession.js

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,51 @@ var RestoreSession = class {
6363
restoreSessionFromFile(session_file_path) {
6464
const session_file = Gio.File.new_for_path(session_file_path);
6565
let [success, contents] = session_file.load_contents(null);
66-
if (success) {
67-
let session_config = FileUtils.getJsonObj(contents);
68-
69-
const session_config_objects = session_config.x_session_config_objects;
70-
if (!session_config_objects) {
71-
logError(new Error(`Session details not found: ${session_file_path}`));
72-
return;
66+
if (!success) {
67+
return;
68+
}
69+
70+
let session_config = FileUtils.getJsonObj(contents);
71+
let session_config_objects = session_config.x_session_config_objects;
72+
if (!session_config_objects) {
73+
logError(new Error(`Session details not found: ${session_file_path}`));
74+
return;
75+
}
76+
77+
session_config_objects = session_config_objects.filter(session_config_object => {
78+
const desktop_file_id = session_config_object.desktop_file_id;
79+
if (!desktop_file_id) {
80+
return true;
7381
}
74-
75-
this._restoreSessionTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
76-
// In milliseconds.
77-
// Note that this timing might not be precise, see https://gjs-docs.gnome.org/glib20~2.66.1/glib.timeout_add
78-
this._restore_session_interval,
79-
() => {
80-
if (session_config_objects.length === 0) {
81-
return GLib.SOURCE_REMOVE;
82-
}
83-
this._restoreSessionOne(session_config_objects.shift());
84-
return GLib.SOURCE_CONTINUE;
82+
const shellApp = this._defaultAppSystem.lookup_app(desktop_file_id)
83+
if (!shellApp) {
84+
return true;
85+
}
86+
87+
if (this._appIsRunning(shellApp)) {
88+
this._log.debug(`${shellApp.get_name()} is already running`)
89+
return false;
90+
}
91+
92+
return true;
93+
});
94+
if (session_config_objects.length === 0) return;
95+
96+
this._restoreSessionOne(session_config_objects.shift());
97+
if (session_config_objects.length === 0) return;
98+
99+
this._restoreSessionTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
100+
// In milliseconds.
101+
// Note that this timing might not be precise, see https://gjs-docs.gnome.org/glib20~2.66.1/glib.timeout_add
102+
this._restore_session_interval,
103+
() => {
104+
if (session_config_objects.length === 0) {
105+
return GLib.SOURCE_REMOVE;
85106
}
86-
);
87-
}
88-
107+
this._restoreSessionOne(session_config_objects.shift());
108+
return GLib.SOURCE_CONTINUE;
109+
}
110+
);
89111
}
90112

91113
_restoreSessionOne(session_config_object) {
@@ -180,7 +202,7 @@ var RestoreSession = class {
180202
const running_apps = this._defaultAppSystem.get_running();
181203
for (const running_app of running_apps) {
182204
if (running_app.get_id() === app.get_id() &&
183-
running_app.get_state() >= Shell.AppState.STARTING) {
205+
running_app.get_state() >= Shell.AppState.STARTING) {
184206
return true;
185207
}
186208
}

0 commit comments

Comments
 (0)