-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextension.js
More file actions
156 lines (156 loc) · 6.33 KB
/
extension.js
File metadata and controls
156 lines (156 loc) · 6.33 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deactivate = exports.activate = void 0;
/**
* PairView Sync — VS Code Extension
*
* Listens for media file activations (images, videos) and automatically
* opens the corresponding data file (.txt, .json, .csv, .xml, .yaml) in
* the adjacent pane, and vice-versa. File type groups are configurable
* through VS Code settings.
*/
const vscode = require("vscode");
const path = require("path");
let statusBarItem;
function activate(context) {
let isOpeningRelated = false;
// --- Status Bar ---
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
statusBarItem.command = 'pairView.toggleSync';
context.subscriptions.push(statusBarItem);
updateStatusBar();
// --- Toggle Command ---
const toggleCommand = vscode.commands.registerCommand('pairView.toggleSync', async () => {
const config = vscode.workspace.getConfiguration('pairView');
const currentState = config.get('enableSync', true);
await config.update('enableSync', !currentState, vscode.ConfigurationTarget.Global);
// Status bar updates via onDidChangeConfiguration below
vscode.window.showInformationMessage(`PairView Sync is now ${!currentState ? 'Enabled' : 'Disabled'}`);
});
context.subscriptions.push(toggleCommand);
// --- Listen for config changes to update status bar ---
const configListener = vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration('pairView')) {
updateStatusBar();
}
});
context.subscriptions.push(configListener);
// --- Tab Change Listener ---
const listener = vscode.window.tabGroups.onDidChangeTabs(async (e) => {
if (isOpeningRelated)
return;
const config = vscode.workspace.getConfiguration('pairView');
const isSyncEnabled = config.get('enableSync', true);
if (!isSyncEnabled)
return;
// Read user-configurable extension lists
const mediaExtensions = config.get('mediaExtensions', defaultMediaExtensions())
.map(ext => ext.toLowerCase().startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`);
const dataExtensions = config.get('dataExtensions', defaultDataExtensions())
.map(ext => ext.toLowerCase().startsWith('.') ? ext.toLowerCase() : `.${ext.toLowerCase()}`);
// Determine which tab became active
const activeTab = e.changed.find((tab) => tab.isActive)
|| e.opened.find((tab) => tab.isActive);
if (!activeTab)
return;
const input = activeTab.input;
if (!input || !input.uri)
return;
const uri = input.uri;
const ext = path.extname(uri.fsPath).toLowerCase();
const dir = path.dirname(uri.fsPath);
const baseName = path.basename(uri.fsPath, ext);
let foundUri = null;
let targetViewColumn = vscode.ViewColumn.Two;
if (mediaExtensions.includes(ext)) {
// Opened a media file → find the matching data file (in priority order)
for (const dataExt of dataExtensions) {
const targetUri = vscode.Uri.file(path.join(dir, `${baseName}${dataExt}`));
try {
await vscode.workspace.fs.stat(targetUri);
foundUri = targetUri;
targetViewColumn = vscode.ViewColumn.Two;
break;
}
catch {
// file doesn't exist, try next
}
}
}
else if (dataExtensions.includes(ext)) {
// Opened a data file → find the matching media file (in priority order)
for (const mediaExt of mediaExtensions) {
const targetUri = vscode.Uri.file(path.join(dir, `${baseName}${mediaExt}`));
try {
await vscode.workspace.fs.stat(targetUri);
foundUri = targetUri;
targetViewColumn = vscode.ViewColumn.One;
break;
}
catch {
// file doesn't exist, try next
}
}
}
if (foundUri) {
try {
isOpeningRelated = true;
const foundExt = path.extname(foundUri.fsPath).toLowerCase();
if (mediaExtensions.includes(foundExt)) {
// Media files (images & videos) open via vscode.open
await vscode.commands.executeCommand('vscode.open', foundUri, {
viewColumn: targetViewColumn,
preserveFocus: true
});
}
else {
// Data/text files open in a text editor
await vscode.window.showTextDocument(foundUri, {
viewColumn: targetViewColumn,
preserveFocus: true,
preview: true
});
}
}
catch (error) {
console.error(`PairView: Error opening related file: ${error}`);
}
finally {
setTimeout(() => {
isOpeningRelated = false;
}, 500);
}
}
});
context.subscriptions.push(listener);
}
exports.activate = activate;
function deactivate() {
if (statusBarItem) {
statusBarItem.dispose();
}
}
exports.deactivate = deactivate;
// --- Helpers ---
function defaultMediaExtensions() {
return [
'.png', '.jpg', '.jpeg', '.webp', '.bmp', '.gif', '.svg', '.tiff', '.tif', '.ico',
'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.webm', '.flv', '.m4v', '.3gp'
];
}
function defaultDataExtensions() {
return ['.txt', '.json', '.csv', '.xml', '.yaml', '.yml'];
}
function updateStatusBar() {
const isSyncEnabled = vscode.workspace.getConfiguration('pairView').get('enableSync', true);
if (isSyncEnabled) {
statusBarItem.text = '$(sync) PairView';
statusBarItem.tooltip = 'PairView Sync is ON — click to disable';
}
else {
statusBarItem.text = '$(sync-ignored) PairView';
statusBarItem.tooltip = 'PairView Sync is OFF — click to enable';
}
statusBarItem.show();
}
//# sourceMappingURL=extension.js.map