Files
nix-flake/assets/dotfiles/vscode-extensions/jdunkel.patternstore-0.1.12/out/webview/WebviewManager.js
T
greyweather 0f018cd2e3 full PC config setup
shifting towards manual symlinks for more complex setup than laptop, allows for GUI settings changes to actually apply, and is much easier than nix-ifying every config
2026-07-12 04:01:28 +01:00

266 lines
10 KiB
JavaScript

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebviewManager = void 0;
const vscode = __importStar(require("vscode"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const storage = __importStar(require("../storage"));
const searchCtx = __importStar(require("../searchCtx"));
/**
* Manages the webview panel for pattern management
*/
class WebviewManager {
/**
* Create or show the webview panel
*/
static show(extensionUri, scope) {
const column = vscode.window.activeTextEditor
? vscode.window.activeTextEditor.viewColumn
: undefined;
// If we already have a panel, show it
if (WebviewManager.currentPanel) {
WebviewManager.currentPanel.panel.reveal(column);
return;
}
const panel = vscode.window.createWebviewPanel('patternStoreManage', 'PatternStore', column || vscode.ViewColumn.One, {
enableScripts: true,
retainContextWhenHidden: true,
});
WebviewManager.currentPanel = new WebviewManager(panel, extensionUri, scope);
}
constructor(panel, extensionUri, scope) {
this.disposables = [];
this.isInternalSave = false;
this.panel = panel;
this.extensionUri = extensionUri;
this.scope = scope;
// Set initial HTML content
this.panel.webview.html = this.getHtmlContent();
// Listen for when the panel is disposed
this.panel.onDidDispose(() => this.dispose(), null, this.disposables);
// Handle messages from the webview
this.panel.webview.onDidReceiveMessage(message => {
this.handleMessage(message);
}, null, this.disposables);
// Watch for external config changes
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('patternStore')) {
this.handleExternalConfigChange();
}
}, null, this.disposables);
this.sendPatterns();
}
sendPatterns(selectId, selectScope, clearSelection) {
const allPatterns = storage.getAllPatterns();
const workspacePatterns = allPatterns.filter(p => p.scope === 'workspace');
const userPatterns = allPatterns.filter(p => p.scope === 'global');
const message = {
type: 'patterns',
workspace: workspacePatterns,
user: userPatterns
};
if (selectId && selectScope) {
message.selectPattern = {
id: selectId,
scope: selectScope
};
}
if (clearSelection) {
message.clearSelection = true;
}
this.panel.webview.postMessage(message);
}
/**
* Handle external configuration changes (e.g., manual edits to settings.json)
*/
handleExternalConfigChange() {
// Don't show notification if this was an internal save
if (this.isInternalSave) {
this.isInternalSave = false;
return;
}
// Show warning to user for actual external changes
vscode.window.showWarningMessage('Pattern settings changed externally. Webview reloaded.');
// Force full reload - this clears any dirty state and rebuilds runtime IDs
// Pass clearSelection flag to force the webview to clear the details view
this.sendPatterns(undefined, undefined, true);
}
async handleMessage(message) {
console.log('Received message from webview:', message);
switch (message.type) {
case 'ready':
// Webview is ready, send patterns
this.sendPatterns();
break;
case 'delete':
await this.handleDelete(message.id, message.scope);
break;
case 'load':
await this.handleLoad(message.id, message.scope, message.pattern);
break;
case 'create':
await this.handleCreate(message.scope);
break;
case 'save':
await this.handleSave(message.pattern);
break;
}
}
async handleCreate(scope) {
// Generate unique label for new pattern
const existingPatterns = storage.getAllPatterns().filter(p => p.scope === scope);
const baseName = 'New Pattern';
let label = baseName;
let counter = 1;
while (existingPatterns.some(p => p.label === label)) {
counter++;
label = `${baseName} ${counter}`;
}
const newPattern = {
id: 'new', // Temporary ID for new patterns
label: label,
find: '',
replace: '',
flags: {
isRegex: false,
isCaseSensitive: false,
matchWholeWord: false,
isMultiline: false
},
scope: scope
};
// Mark as internal save to suppress external change notification
this.isInternalSave = true;
await storage.savePattern(newPattern);
// New pattern will be at index 0 (savePattern uses unshift)
this.sendPatterns(`${scope}-0`, scope);
}
async handleSave(patternData) {
const { id, label, find, replace, flags, filesToInclude, filesToExclude, scope } = patternData;
const pattern = {
id: id, // Preserve existing ID
label: label,
find: find,
replace: replace,
flags: flags,
filesToInclude: filesToInclude,
filesToExclude: filesToExclude,
scope: scope
};
// Mark as internal save to suppress external change notification
this.isInternalSave = true;
await storage.savePattern(pattern);
this.sendPatterns(id, scope);
}
async handleDelete(id, scope) {
// Find pattern to get label for confirmation
const allPatterns = storage.getAllPatterns();
const pattern = allPatterns.find(p => p.id === id && p.scope === scope);
if (!pattern) {
vscode.window.showErrorMessage(`Pattern not found`);
return;
}
// Confirm deletion
const confirm = await vscode.window.showWarningMessage(`Delete pattern "${pattern.label}"?`, { modal: true }, 'Delete');
if (confirm === 'Delete') {
// Mark as internal save to suppress external change notification
this.isInternalSave = true;
await storage.deletePattern(id, scope);
// Refresh pattern list
this.sendPatterns();
}
}
async handleLoad(id, scope, providedPattern) {
let pattern = providedPattern;
// If no pattern was provided, look it up
if (!pattern) {
const allPatterns = storage.getAllPatterns();
pattern = allPatterns.find(p => p.id === id && p.scope === scope);
if (!pattern) {
vscode.window.showErrorMessage(`Pattern "${id}" not found`);
return;
}
}
await searchCtx.loadPatternIntoSearch(pattern);
}
getHtmlContent() {
// Generate nonce for CSP
const nonce = this.getNonce();
// Get URIs for webview resources
const cspSource = this.panel.webview.cspSource;
// Load HTML, CSS, and JS from files
const htmlPath = path.join(this.extensionUri.fsPath, 'src', 'webview', 'html', 'patternManager.html');
const cssPath = path.join(this.extensionUri.fsPath, 'src', 'webview', 'css', 'patternManager.css');
const jsPath = path.join(this.extensionUri.fsPath, 'src', 'webview', 'js', 'patternManager.js');
let html = fs.readFileSync(htmlPath, 'utf8');
const css = fs.readFileSync(cssPath, 'utf8');
const js = fs.readFileSync(jsPath, 'utf8');
// Build style tag with nonce
const styleTag = `<style nonce="${nonce}">\n${css}\n </style>`;
// Replace placeholders
html = html.replace(/{{nonce}}/g, nonce);
html = html.replace(/{{cspSource}}/g, cspSource);
html = html.replace(/{{styleTag}}/g, styleTag);
html = html.replace(/{{script}}/g, js);
return html;
}
/**
* Generate a nonce for CSP
*/
getNonce() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
/**
* Clean up resources
*/
dispose() {
WebviewManager.currentPanel = undefined;
this.panel.dispose();
while (this.disposables.length) {
const disposable = this.disposables.pop();
if (disposable) {
disposable.dispose();
}
}
}
}
exports.WebviewManager = WebviewManager;
//# sourceMappingURL=WebviewManager.js.map