diff --git a/gnome-extension/schemas/gschemas.compiled b/gnome-extension/schemas/gschemas.compiled
index 73c210a..b940662 100644
Binary files a/gnome-extension/schemas/gschemas.compiled and b/gnome-extension/schemas/gschemas.compiled differ
diff --git a/gnome-extension/schemas/org.gnome.shell.extensions.vscode-workspaces.gschema.xml b/gnome-extension/schemas/org.gnome.shell.extensions.vscode-workspaces.gschema.xml
index 6535f42..06e5807 100644
--- a/gnome-extension/schemas/org.gnome.shell.extensions.vscode-workspaces.gschema.xml
+++ b/gnome-extension/schemas/org.gnome.shell.extensions.vscode-workspaces.gschema.xml
@@ -2,10 +2,11 @@
-
- 'code'
- VSCode Location
- Path to your VSCode Binary
+
+ 'auto'
+ Editor Location
+ Path to your editor binary (code, codium, code-insiders) or 'auto' for
+ automatic detection
false
@@ -15,7 +16,8 @@
false
Prefer Workspace File
- Whether to prefer the workspace file over the workspace directory if a workspace file is present
+ Whether to prefer the workspace file over the workspace directory if a
+ workspace file is present
false
@@ -28,4 +30,4 @@
Refresh Interval for the scanning workspaces, in Seconds
-
\ No newline at end of file
+
diff --git a/gnome-extension/src/extension.ts b/gnome-extension/src/extension.ts
index 161c62b..7fc1808 100644
--- a/gnome-extension/src/extension.ts
+++ b/gnome-extension/src/extension.ts
@@ -28,42 +28,59 @@ interface RecentWorkspace {
removeWorkspaceItem: () => void;
}
+interface EditorPath {
+ name: string;
+ binary: string;
+ workspacePath: string;
+ isDefault?: boolean;
+}
+
export default class VSCodeWorkspacesExtension extends Extension {
gsettings?: Gio.Settings;
- _indicator?: PanelMenu.Button;
-
- _refreshInterval: number = 300;
- _refreshTimeout: any = null;
- _newWindow: boolean = false;
- _vscodeLocation: string = '';
- _preferCodeWorkspaceFile: boolean = false;
- _debug: boolean = false;
-
- _recentWorkspacesPath: string = GLib.build_filenamev([
- GLib.get_home_dir(),
- '.config/Code/User/workspaceStorage',
- ]);
- _workspaces: Set = new Set();
- _recentWorkspaces: Set = new Set();
-
- // TODO: Implement notifications
- //_messageTray: MessageTray.MessageTray | null = null;
- //_notificationSource: MessageTray.Source | null = null;
- //_notification: MessageTray.Notification | null = null;
+
+ private _indicator?: PanelMenu.Button;
+ private _refreshInterval: number = 300;
+ private _refreshTimeout: any = null;
+ private _newWindow: boolean = false;
+ private _editorLocation: string = '';
+ private _preferCodeWorkspaceFile: boolean = false;
+ private _debug: boolean = false;
+ private _workspaces: Set = new Set();
+ private _recentWorkspaces: Set = new Set();
+ private readonly _userConfigDir: string = GLib.build_filenamev([GLib.get_home_dir(), '.config']);
+ private _foundEditors: EditorPath[] = [];
+ private _activeEditor?: EditorPath;
+ private readonly _editors: EditorPath[] = [
+ {
+ name: 'vscode',
+ binary: 'code',
+ workspacePath: GLib.build_filenamev([this._userConfigDir, 'Code/User/workspaceStorage']),
+ isDefault: true,
+ },
+ {
+ name: 'codium',
+ binary: 'codium',
+ workspacePath: GLib.build_filenamev([this._userConfigDir, 'VSCodium/User/workspaceStorage']),
+ },
+ {
+ name: 'code-insiders',
+ binary: 'code-insiders',
+ workspacePath: GLib.build_filenamev([this._userConfigDir, 'Code - Insiders/User/workspaceStorage']),
+ },
+ ];
+ private readonly _iconNames = ['vscode', 'code', 'vscodium', 'codium', 'code-insiders'];
enable() {
this.gsettings = this.getSettings();
this._indicator = new PanelMenu.Button(0.0, this.metadata.name, false);
- // check if the vscode icon exists, or the code icon exists
- // if it doesn't, use the default
- let iconName: string = 'vscode';
-
- if (!this._iconExists('vscode')) {
- iconName = 'code';
- } else if (!this._iconExists('code')) {
- iconName = 'vscode';
+ let iconName = 'code';
+ for (const name of this._iconNames) {
+ if (this._iconExists(name)) {
+ iconName = iconName;
+ break;
+ }
}
const icon = new St.Icon({
@@ -83,6 +100,60 @@ export default class VSCodeWorkspacesExtension extends Extension {
this._setSettings();
this._startRefresh();
});
+
+ this._initializeWorkspaces();
+ }
+
+ _initializeWorkspaces() {
+ this._log('Initializing workspaces');
+ this._workspaces.clear();
+ this._recentWorkspaces.clear();
+ this._foundEditors = [];
+
+ for (const editor of this._editors) {
+ const dir = Gio.File.new_for_path(editor.workspacePath);
+
+ this._log(`Checking for ${editor.name} workspace storage directory: ${editor.workspacePath}`);
+
+ if (!dir.query_exists(null)) {
+ this._log(`No ${editor.name} workspace storage directory found: ${editor.workspacePath}`);
+ continue;
+ }
+
+ this._log(`Found ${editor.name} workspace storage directory: ${editor.workspacePath}`);
+ this._foundEditors.push(editor);
+ }
+
+ this._log(`Found editors: ${this._foundEditors.map(editor => editor.name)}`);
+
+ this._setActiveEditor();
+
+ this._log(`Active editor: ${this._activeEditor?.name}`);
+
+ if (!this._activeEditor) {
+ this._log('No active editor found');
+ return;
+ }
+ this._getRecentWorkspaces();
+ }
+
+ _setActiveEditor() {
+ const editorLocation = this._editorLocation;
+ if (editorLocation === 'auto') {
+ this._activeEditor = this._foundEditors.find(editor => editor.isDefault) ?? this._foundEditors[0];
+ } else {
+ this._activeEditor = this._foundEditors.find(editor => editor.binary === editorLocation) ?? this._foundEditors[0];
+ }
+
+ if (!this._activeEditor && this._foundEditors.length > 0) {
+ this._activeEditor = this._foundEditors[0];
+ }
+
+ if (this._activeEditor) {
+ this._log(`Active editor set to: ${this._activeEditor.name}`);
+ } else {
+ this._log('No editor found!');
+ }
}
disable() {
@@ -95,51 +166,72 @@ export default class VSCodeWorkspacesExtension extends Extension {
this._indicator = undefined;
}
this.gsettings = undefined;
- //this._recentWorkspaces = null;
- //this._workspaces = null;
// clean up the cache
this._workspaces.clear();
this._recentWorkspaces.clear();
+ this._foundEditors = [];
+ this._activeEditor = undefined;
this._log(`VSCode Workspaces Extension disabled`);
}
_setSettings() {
this._newWindow = this.gsettings!.get_value('new-window').deepUnpack() ?? false;
- this._vscodeLocation = this.gsettings!.get_value('vscode-location').deepUnpack() ?? 'code';
+ this._editorLocation = this.gsettings!.get_value('editor-location').deepUnpack() ?? 'auto';
this._refreshInterval = this.gsettings!.get_value('refresh-interval').deepUnpack() ?? 300;
this._preferCodeWorkspaceFile = this.gsettings!.get_value('prefer-workspace-file').deepUnpack() ?? false;
this._debug = this.gsettings!.get_value('debug').deepUnpack() ?? false;
- this._log(`VSCode Workspaces Extension enabled`);
+ this._log(`Workspaces Extension enabled`);
this._log(`New Window: ${this._newWindow}`);
- this._log(`VSCode Location: ${this._vscodeLocation}`);
+ this._log(`Workspaces Storage Location: ${this._editorLocation}`);
this._log(`Refresh Interval: ${this._refreshInterval}`);
this._log(`Prefer Code Workspace File: ${this._preferCodeWorkspaceFile}`);
this._log(`Debug: ${this._debug}`);
}
_iconExists(iconName: string): boolean {
- const theme = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
- const iconThemeName = theme.get_string('icon-theme');
- const iconTheme = new Gio.ThemedIcon({ name: iconThemeName });
-
try {
- const iconInfo = iconTheme.get_names().filter(icon => icon === iconName);
- return iconInfo !== null;
+ const iconTheme = St.IconTheme.new();
+ return iconTheme.has_icon(iconName);
} catch (error) {
logError(error as object, 'Failed to check if icon exists');
return false;
}
}
-
_createMenu() {
if (!this._indicator) return;
(this._indicator.menu as PopupMenu.PopupMenu).removeAll();
+ // Add editor selector if multiple editors are found
+ if (this._foundEditors.length > 1) {
+ const editorSelector = new PopupMenu.PopupSubMenuMenuItem('Select Editor');
+
+ this._foundEditors.forEach(editor => {
+ const item = new PopupMenu.PopupMenuItem(editor.name);
+ const isActive = this._activeEditor?.binary === editor.binary;
+
+ if (isActive) {
+ item.setOrnament(PopupMenu.Ornament.DOT);
+ }
+
+ item.connect('activate', () => {
+ this._editorLocation = editor.binary;
+ this.gsettings?.set_string('editor-location', editor.binary);
+ this._setActiveEditor();
+ this._createMenu();
+ });
+
+ editorSelector.menu.addMenuItem(item);
+ });
+
+ (this._indicator.menu as PopupMenu.PopupMenu).addMenuItem(editorSelector);
+ (this._indicator.menu as PopupMenu.PopupMenu).addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ }
+
this._loadRecentWorkspaces();
const itemSettings = new PopupMenu.PopupSubMenuMenuItem('Settings');
@@ -359,18 +451,9 @@ export default class VSCodeWorkspacesExtension extends Extension {
}
}
- _log(message: any): void {
-
- if (!this._debug) {
- return;
- }
-
- log(`[${this.metadata.name}]: ${message}`);
- }
-
_getRecentWorkspaces() {
try {
- const dir = Gio.File.new_for_path(this._recentWorkspacesPath);
+ const dir = Gio.File.new_for_path(this._activeEditor?.workspacePath!);
this._iterateWorkspaceDir(dir, workspace => {
//! This callback checks if the workspace exists and if it is a directory, it checks if there is a `.code-workspace` file in the directory
@@ -583,11 +666,11 @@ export default class VSCodeWorkspacesExtension extends Extension {
newWindow = '--new-window';
}
- const command = `${this._vscodeLocation} ${newWindow} ${args} ${safePaths}`;
+ const command = `${this._activeEditor?.binary} ${newWindow} ${args} ${safePaths}`;
this._log(`Command to execute: ${command}`);
GLib.spawn_command_line_async(command);
} catch (error) {
- logError(error as object, 'Failed to launch VSCode');
+ logError(error as object, `Failed to launch ${this._activeEditor?.name}`);
}
}
@@ -602,22 +685,22 @@ export default class VSCodeWorkspacesExtension extends Extension {
try {
if (
!GLib.file_test(
- this._recentWorkspacesPath,
+ this._activeEditor?.workspacePath!,
GLib.FileTest.EXISTS | GLib.FileTest.IS_DIR
)
) {
throw new Error('Recent workspaces directory does not exist');
}
// Create a backup of the directory before deleting it
- const backupPath = `${this._recentWorkspacesPath}.bak`;
+ const backupPath = `${this._activeEditor?.workspacePath!}.bak`;
const backupDir = Gio.File.new_for_path(backupPath);
- const recentWorkspacesDir = Gio.File.new_for_path(this._recentWorkspacesPath);
+ const recentWorkspacesDir = Gio.File.new_for_path(this._activeEditor?.workspacePath!);
if (backupDir.query_exists(null)) {
throw new Error('Backup directory already exists');
}
- this._log(`Creating backup of ${this._recentWorkspacesPath} to ${backupPath}`);
+ this._log(`Creating backup of ${this._activeEditor?.workspacePath!} to ${backupPath}`);
const res = recentWorkspacesDir.copy(
backupDir,
@@ -702,4 +785,12 @@ export default class VSCodeWorkspacesExtension extends Extension {
}
);
}
+
+ _log(message: any): void {
+ if (!this._debug) {
+ return;
+ }
+
+ log(`[${this.metadata.name}]: ${message}`);
+ }
}
diff --git a/gnome-extension/src/prefs.ts b/gnome-extension/src/prefs.ts
index 5591bb1..c65f2aa 100644
--- a/gnome-extension/src/prefs.ts
+++ b/gnome-extension/src/prefs.ts
@@ -18,24 +18,24 @@ export default class VSCodeWorkspacesPreferences extends ExtensionPreferences {
// Group for New Window setting
const newWindowGroup = new Adw.PreferencesGroup({
title: _('New Window'),
- description: _('Configure whether to open VSCode in a new window'),
+ description: _('Configure whether to open editor in a new window'),
});
page.add(newWindowGroup);
const newWindowSwitch = new Adw.SwitchRow({
title: _('Open in New Window'),
- subtitle: _('Whether to open VSCode in a new window'),
+ subtitle: _('Whether to open editor in a new window'),
});
newWindowGroup.add(newWindowSwitch);
- // Group for VSCode Location
- const vscodeGroup = new Adw.PreferencesGroup({
- title: _('VSCode Settings'),
- description: _('Configure various settings for interacting with VSCode'),
+ // Group for editor Location
+ const editorGroup = new Adw.PreferencesGroup({
+ title: _('editor Settings'),
+ description: _('Configure various settings for interacting with editor'),
});
- const vscodeLocation = new Adw.EntryRow({
- title: _('VSCode Location'),
+ const editorLocation = new Adw.EntryRow({
+ title: _('editor Location'),
showApplyButton: true,
inputPurpose: Gtk.InputPurpose.TERMINAL,
inputHints: Gtk.InputHints.WORD_COMPLETION,
@@ -51,10 +51,10 @@ export default class VSCodeWorkspacesPreferences extends ExtensionPreferences {
subtitle: _('Whether to prefer the workspace file over the workspace directory if a workspace file is present'),
});
- vscodeGroup.add(vscodeLocation);
- vscodeGroup.add(preferWorkspaceFile);
- vscodeGroup.add(debug);
- page.add(vscodeGroup);
+ editorGroup.add(editorLocation);
+ editorGroup.add(preferWorkspaceFile);
+ editorGroup.add(debug);
+ page.add(editorGroup);
// Group for Refresh Interval setting
const refreshIntervalGroup = new Adw.PreferencesGroup({
@@ -80,8 +80,8 @@ export default class VSCodeWorkspacesPreferences extends ExtensionPreferences {
Gio.SettingsBindFlags.DEFAULT
);
_settings.bind(
- 'vscode-location',
- vscodeLocation,
+ 'editor-location',
+ editorLocation,
'text',
Gio.SettingsBindFlags.DEFAULT
);
diff --git a/gnome-extension/src/types/ambient.d.ts b/gnome-extension/src/types/ambient.d.ts
index d61627a..8176852 100644
--- a/gnome-extension/src/types/ambient.d.ts
+++ b/gnome-extension/src/types/ambient.d.ts
@@ -1,11 +1,13 @@
-import '@girs/gjs';
-import '@girs/gjs/dom';
-import '@girs/gnome-shell/ambient';
-import '@girs/gnome-shell/extensions/global';
-import '@girs/gnome-shell/gio';
-import '@girs/gnome-shell/meta';
-import '@girs/gnome-shell/shell';
-import '@girs/gnome-shell/st';
-import '@girs/gnome-shell/ui/main';
-import '@girs/gnome-shell/ui/panelMenu';
-import '@girs/gnome-shell/ui/popupMenu';
+import '@girs/gjs';
+import '@girs/gjs/dom';
+import '@girs/gnome-shell/ambient';
+import '@girs/gnome-shell/extensions/global';
+import '@girs/gnome-shell/gio';
+import '@girs/gnome-shell/meta';
+import '@girs/gnome-shell/shell';
+import '@girs/gnome-shell/st';
+import '@girs/gnome-shell/ui/main';
+import '@girs/gnome-shell/ui/panelMenu';
+import '@girs/gnome-shell/ui/popupMenu';
+//import '@girs/gtk-4.0';
+//import '@girs/gdk-4.0';