-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathextension.js
133 lines (116 loc) · 5.75 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* Edit Desktop Files for GNOME Shell 45+
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import GLib from 'gi://GLib';
import {Extension, InjectionManager, gettext} from 'resource:///org/gnome/shell/extensions/extension.js';
import {AppMenu} from 'resource:///org/gnome/shell/ui/appMenu.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
/*
* The Edit Desktop Files extension provides users with an "Edit" button on the pop-up menu
* that appears when right-clicking an app icon in the app grid or dash.
* When clicked, the backing desktop file is opened in an editor.
*
* This is done by injecting a function to run prior to the gnome-shell AppMenu's 'open' method.
* The function inserts a new "Edit" MenuItem that, when clicked, either opens the backing desktop
* file with the GNOME Text Editor (default) or a custom command supplied by the user.
*/
export default class EditDesktopFilesExtension extends Extension {
enable() {
this._settings = this.getSettings();
this._injectionManager = new InjectionManager();
this._modifiedMenus = []
this._addedMenuItems = []
// Call gettext here explicitly so "Edit" can be localized as part of this extension
let localizedEditStr = gettext('Edit')
// Extend the AppMenu's 'open' method to add an 'Edit' MenuItem
// See: https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/appMenu.js
this._injectionManager.overrideMethod(AppMenu.prototype, 'open',
originalMethod => {
const metadata = this.metadata;
const settings = this.getSettings();
const modifiedMenus = this._modifiedMenus;
const addedMenuItems = this._addedMenuItems;
return function (...args) {
// Suitably awful name to ensure it doesn't conflict with an existing/future property
if (this._editDesktopFilesExtensionMenuItem) {
return originalMethod.call(this, ...args);
}
// Don't display the menu item for windows not backed by a desktop file
const appInfo = this._app?.app_info;
if (!appInfo) {
return originalMethod.call(this, ...args);
}
// Add the 'Edit' MenuItem
let editMenuItem = this.addAction(localizedEditStr, () => {
// Open the GNOME Text Editor by default, otherwise use the command provided by the user
let editCommand = `gapplication launch org.gnome.TextEditor '${appInfo.filename}'`
if (settings.get_boolean("use-custom-edit-command")) {
let customEditCommand = settings.get_string("custom-edit-command")
// If the user forgot to include %U in the command, fallback to the default with a warning
if (customEditCommand.indexOf('%U') != -1) {
editCommand = customEditCommand.replace('%U', `'${appInfo.filename}'`)
} else {
console.warn(`${metadata.name}: Custom edit command is missing '%U', falling back to default GNOME Text Editor`)
}
}
GLib.spawn_command_line_async(editCommand);
if(Main.overview.visible) {
Main.overview.hide();
}
})
// Move the 'Edit' MenuItem to be after the 'App Details' MenuItem
let menuItems = this._getMenuItems()
for (let i = 0; i < menuItems.length; i++) {
let menuItem = menuItems[i]
if (menuItem.label) {
if (menuItem.label.text == _('App Details')) {
this.moveMenuItem(editMenuItem, i+1)
break;
}
}
}
// Keep track of menus that have been affected so they can be cleaned up later
this._editDesktopFilesExtensionMenuItem = editMenuItem
modifiedMenus.push(this)
addedMenuItems.push(editMenuItem)
return originalMethod.call(this, ...args);
};
}
);
}
disable() {
this._settings = null
this._injectionManager.clear();
this._injectionManager = null;
this.removeAllMenuItems()
this._addedMenuItems = null
this._modifiedMenus = null
}
removeAllMenuItems() {
// Delete the added properties
for (let menu of this._modifiedMenus) {
delete menu._editDesktopFilesExtensionMenuItem
}
// Delete all added MenuItems
for (let menuItem of this._addedMenuItems) {
menuItem.destroy();
}
this._addedMenuItems = []
this._modifiedMenus = []
}
}