mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-17 16:37:43 +00:00
refactor: use PluginLog for all logging in plugins directory
- Replaced all Log.* calls with PluginLog.* in plugins directory - Modified 14 files with 179 total changes - Removed unused Log imports - All plugin-related logs now have [plugin] context prefix This ensures consistent context-aware logging for all plugin operations, making it easier to filter and debug plugin-related issues.
This commit is contained in:
parent
fd099ed4a1
commit
5007038fe8
16 changed files with 370 additions and 196 deletions
146
scripts/migrate-to-plugin-log.ts
Executable file
146
scripts/migrate-to-plugin-log.ts
Executable file
|
|
@ -0,0 +1,146 @@
|
|||
#!/usr/bin/env ts-node
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as glob from 'glob';
|
||||
|
||||
interface Replacement {
|
||||
pattern: RegExp;
|
||||
replacement: string;
|
||||
}
|
||||
|
||||
const replacements: Replacement[] = [
|
||||
// Replace Log.log with PluginLog.log
|
||||
{ pattern: /\bLog\.log\(/g, replacement: 'PluginLog.log(' },
|
||||
// Replace Log.err with PluginLog.err
|
||||
{ pattern: /\bLog\.err\(/g, replacement: 'PluginLog.err(' },
|
||||
// Replace Log.info with PluginLog.info
|
||||
{ pattern: /\bLog\.info\(/g, replacement: 'PluginLog.info(' },
|
||||
// Replace Log.debug with PluginLog.debug
|
||||
{ pattern: /\bLog\.debug\(/g, replacement: 'PluginLog.debug(' },
|
||||
// Replace Log.verbose with PluginLog.verbose
|
||||
{ pattern: /\bLog\.verbose\(/g, replacement: 'PluginLog.verbose(' },
|
||||
// Replace Log.critical with PluginLog.critical
|
||||
{ pattern: /\bLog\.critical\(/g, replacement: 'PluginLog.critical(' },
|
||||
];
|
||||
|
||||
function updateImports(content: string): string {
|
||||
// Check if file already imports PluginLog
|
||||
const hasPluginLogImport =
|
||||
/import\s*{[^}]*\bPluginLog\b[^}]*}\s*from\s*['"][^'"]*\/log['"]/.test(content);
|
||||
|
||||
if (hasPluginLogImport) {
|
||||
// If PluginLog is already imported, just remove Log from the import if it's not used elsewhere
|
||||
return content;
|
||||
}
|
||||
|
||||
// Find existing Log import and add PluginLog to it
|
||||
const logImportRegex = /import\s*{([^}]*\bLog\b[^}]*)}\s*from\s*(['"][^'"]*\/log['"])/;
|
||||
const match = content.match(logImportRegex);
|
||||
|
||||
if (match) {
|
||||
const [fullMatch, imports, importPath] = match;
|
||||
const importList = imports.split(',').map((s) => s.trim());
|
||||
|
||||
// Add PluginLog if not already there
|
||||
if (!importList.includes('PluginLog')) {
|
||||
importList.push('PluginLog');
|
||||
}
|
||||
|
||||
// Check if Log is still used after replacements
|
||||
let tempContent = content;
|
||||
for (const { pattern, replacement } of replacements) {
|
||||
tempContent = tempContent.replace(pattern, replacement);
|
||||
}
|
||||
|
||||
// Remove the import statement from check
|
||||
tempContent = tempContent.replace(logImportRegex, '');
|
||||
|
||||
// If Log is no longer used, remove it from imports
|
||||
const logStillUsed = /\bLog\b/.test(tempContent);
|
||||
if (!logStillUsed) {
|
||||
const logIndex = importList.indexOf('Log');
|
||||
if (logIndex > -1) {
|
||||
importList.splice(logIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const newImports = importList.join(', ');
|
||||
const newImportStatement = `import { ${newImports} } from ${importPath}`;
|
||||
content = content.replace(fullMatch, newImportStatement);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
function processFile(filePath: string): { modified: boolean; changes: number } {
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
const originalContent = content;
|
||||
let changeCount = 0;
|
||||
|
||||
// Count and apply replacements
|
||||
for (const { pattern, replacement } of replacements) {
|
||||
const matches = content.match(pattern);
|
||||
if (matches) {
|
||||
changeCount += matches.length;
|
||||
content = content.replace(pattern, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
// Update imports if changes were made
|
||||
if (changeCount > 0) {
|
||||
content = updateImports(content);
|
||||
}
|
||||
|
||||
const modified = content !== originalContent;
|
||||
|
||||
if (modified) {
|
||||
fs.writeFileSync(filePath, content, 'utf8');
|
||||
}
|
||||
|
||||
return { modified, changes: changeCount };
|
||||
} catch (error) {
|
||||
console.error(`Error processing ${filePath}:`, error);
|
||||
return { modified: false, changes: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('Migrating Log to PluginLog in plugins directory...\n');
|
||||
|
||||
// Find all TypeScript files in plugins directory
|
||||
const files = glob.sync('src/app/plugins/**/*.ts', {
|
||||
ignore: ['**/*.spec.ts', '**/node_modules/**'],
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
console.log(`Found ${files.length} TypeScript files in plugins directory\n`);
|
||||
|
||||
const modifiedFiles: { path: string; changes: number }[] = [];
|
||||
let totalChanges = 0;
|
||||
|
||||
for (const file of files) {
|
||||
const result = processFile(file);
|
||||
if (result.modified) {
|
||||
modifiedFiles.push({ path: file, changes: result.changes });
|
||||
totalChanges += result.changes;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\nMigration complete!\n');
|
||||
console.log(`Total changes: ${totalChanges}`);
|
||||
console.log(`Modified ${modifiedFiles.length} files:\n`);
|
||||
|
||||
modifiedFiles
|
||||
.sort((a, b) => b.changes - a.changes)
|
||||
.forEach(({ path: filePath, changes }) => {
|
||||
console.log(` - ${path.relative(process.cwd(), filePath)} (${changes} changes)`);
|
||||
});
|
||||
|
||||
if (modifiedFiles.length === 0) {
|
||||
console.log(' No files needed modification.');
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -241,4 +241,5 @@ export class Log {
|
|||
// Pre-configured logger instances for specific contexts
|
||||
// All context loggers now record to history
|
||||
export const SyncLog = Log.withContext('sync');
|
||||
export const PFLog = Log.withContext('pf');
|
||||
export const PluginLog = Log.withContext('plugin');
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import {
|
|||
PluginManifest,
|
||||
} from '@super-productivity/plugin-api';
|
||||
import { PluginBridgeService } from './plugin-bridge.service';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
import {
|
||||
taskCopyToTaskData,
|
||||
projectCopyToProjectData,
|
||||
|
|
@ -67,7 +67,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
pluginHooks.get(hook)!.push(fn);
|
||||
Log.log(`Plugin ${this._pluginId} registered hook: ${hook}`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} registered hook: ${hook}`);
|
||||
|
||||
// Register hook with bridge
|
||||
this._pluginBridge.registerHook(this._pluginId, hook, fn);
|
||||
|
|
@ -75,14 +75,14 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
|
||||
registerHeaderButton(headerBtnCfg: PluginHeaderBtnCfg): void {
|
||||
this._headerButtons.push({ ...headerBtnCfg, pluginId: this._pluginId });
|
||||
Log.log(`Plugin ${this._pluginId} registered header button`, headerBtnCfg);
|
||||
PluginLog.log(`Plugin ${this._pluginId} registered header button`, headerBtnCfg);
|
||||
this._pluginBridge.registerHeaderButton(headerBtnCfg);
|
||||
}
|
||||
|
||||
registerMenuEntry(menuEntryCfg: Omit<PluginMenuEntryCfg, 'pluginId'>): void {
|
||||
const fullMenuEntry = { ...menuEntryCfg, pluginId: this._pluginId };
|
||||
this._menuEntries.push(fullMenuEntry);
|
||||
Log.log(`Plugin ${this._pluginId} registered menu entry`, menuEntryCfg);
|
||||
PluginLog.log(`Plugin ${this._pluginId} registered menu entry`, menuEntryCfg);
|
||||
this._pluginBridge.registerMenuEntry(menuEntryCfg);
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
};
|
||||
|
||||
this._shortcuts.push(shortcut);
|
||||
Log.log(`Plugin ${this._pluginId} registered shortcut`, shortcutCfg);
|
||||
PluginLog.log(`Plugin ${this._pluginId} registered shortcut`, shortcutCfg);
|
||||
|
||||
// Register shortcut with bridge
|
||||
this._pluginBridge.registerShortcut(shortcut);
|
||||
|
|
@ -110,58 +110,64 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
sidePanelBtnCfg: Omit<PluginSidePanelBtnCfg, 'pluginId'>,
|
||||
): void {
|
||||
this._sidePanelButtons.push({ ...sidePanelBtnCfg, pluginId: this._pluginId });
|
||||
Log.log(`Plugin ${this._pluginId} registered side panel button`, sidePanelBtnCfg);
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} registered side panel button`,
|
||||
sidePanelBtnCfg,
|
||||
);
|
||||
this._pluginBridge.registerSidePanelButton(sidePanelBtnCfg);
|
||||
}
|
||||
|
||||
showIndexHtmlAsView(): void {
|
||||
Log.log(`Plugin ${this._pluginId} requested to show index.html`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to show index.html`);
|
||||
return this._pluginBridge.showIndexHtmlAsView(this._pluginId);
|
||||
}
|
||||
|
||||
async getTasks(): Promise<Task[]> {
|
||||
Log.log(`Plugin ${this._pluginId} requested all tasks`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested all tasks`);
|
||||
const tasks = await this._pluginBridge.getTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async getArchivedTasks(): Promise<Task[]> {
|
||||
Log.log(`Plugin ${this._pluginId} requested archived tasks`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested archived tasks`);
|
||||
const tasks = await this._pluginBridge.getArchivedTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async getCurrentContextTasks(): Promise<Task[]> {
|
||||
Log.log(`Plugin ${this._pluginId} requested current context tasks`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested current context tasks`);
|
||||
const tasks = await this._pluginBridge.getCurrentContextTasks();
|
||||
return tasks.map(taskCopyToTaskData);
|
||||
}
|
||||
|
||||
async updateTask(taskId: string, updates: Partial<Task>): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to update task ${taskId}:`, updates);
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to update task ${taskId}:`,
|
||||
updates,
|
||||
);
|
||||
const taskCopyUpdates = taskDataToPartialTaskCopy(updates);
|
||||
return this._pluginBridge.updateTask(taskId, taskCopyUpdates);
|
||||
}
|
||||
|
||||
async addTask(taskData: PluginCreateTaskData): Promise<string> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to add task:`, taskData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add task:`, taskData);
|
||||
return this._pluginBridge.addTask(taskData);
|
||||
}
|
||||
|
||||
async getAllProjects(): Promise<Project[]> {
|
||||
Log.log(`Plugin ${this._pluginId} requested all projects`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested all projects`);
|
||||
const projects = await this._pluginBridge.getAllProjects();
|
||||
return projects.map(projectCopyToProjectData);
|
||||
}
|
||||
|
||||
async addProject(projectData: Partial<Project>): Promise<string> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to add project:`, projectData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add project:`, projectData);
|
||||
const projectCopyData = projectDataToPartialProjectCopy(projectData);
|
||||
return this._pluginBridge.addProject(projectCopyData);
|
||||
}
|
||||
|
||||
async updateProject(projectId: string, updates: Partial<Project>): Promise<void> {
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to update project ${projectId}:`,
|
||||
updates,
|
||||
);
|
||||
|
|
@ -170,19 +176,19 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async getAllTags(): Promise<Tag[]> {
|
||||
Log.log(`Plugin ${this._pluginId} requested all tags`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested all tags`);
|
||||
const tags = await this._pluginBridge.getAllTags();
|
||||
return tags.map(tagCopyToTagData);
|
||||
}
|
||||
|
||||
async addTag(tagData: Partial<Tag>): Promise<string> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to add tag:`, tagData);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to add tag:`, tagData);
|
||||
const tagCopyData = tagDataToPartialTagCopy(tagData);
|
||||
return this._pluginBridge.addTag(tagCopyData);
|
||||
}
|
||||
|
||||
async updateTag(tagId: string, updates: Partial<Tag>): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to update tag ${tagId}:`, updates);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to update tag ${tagId}:`, updates);
|
||||
const tagCopyUpdates = tagDataToPartialTagCopy(updates);
|
||||
return this._pluginBridge.updateTag(tagId, tagCopyUpdates);
|
||||
}
|
||||
|
|
@ -192,7 +198,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
contextId: string,
|
||||
contextType: 'project' | 'task',
|
||||
): Promise<void> {
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Plugin ${this._pluginId} requested to reorder tasks in ${contextType} ${contextId}:`,
|
||||
taskIds,
|
||||
);
|
||||
|
|
@ -204,27 +210,27 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
}
|
||||
|
||||
async notify(notifyCfg: NotifyCfg): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested notification:`, notifyCfg);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested notification:`, notifyCfg);
|
||||
return this._pluginBridge.notify(notifyCfg);
|
||||
}
|
||||
|
||||
persistDataSynced(dataStr: string): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to persist data:`, dataStr);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to persist data:`, dataStr);
|
||||
return this._pluginBridge.persistDataSynced(dataStr);
|
||||
}
|
||||
|
||||
loadSyncedData(): Promise<string | null> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to load persisted data:`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to load persisted data:`);
|
||||
return this._pluginBridge.loadPersistedData();
|
||||
}
|
||||
|
||||
async openDialog(dialogCfg: DialogCfg): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to open dialog:`, dialogCfg);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to open dialog:`, dialogCfg);
|
||||
return this._pluginBridge.openDialog(dialogCfg);
|
||||
}
|
||||
|
||||
async triggerSync(): Promise<void> {
|
||||
Log.log(`Plugin ${this._pluginId} requested to trigger sync`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to trigger sync`);
|
||||
return this._pluginBridge.triggerSync();
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +240,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
*/
|
||||
onMessage(handler: (message: any) => Promise<any>): void {
|
||||
this._messageHandler = handler;
|
||||
Log.log(`Plugin ${this._pluginId} registered message handler`);
|
||||
PluginLog.log(`Plugin ${this._pluginId} registered message handler`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -266,7 +272,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
* Execute an NgRx action if it's in the allowed list
|
||||
*/
|
||||
dispatchAction(action: any): void {
|
||||
Log.log(`Plugin ${this._pluginId} requested to execute action:`, action);
|
||||
PluginLog.log(`Plugin ${this._pluginId} requested to execute action:`, action);
|
||||
return this._pluginBridge.dispatchAction(action);
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +281,7 @@ export class PluginAPI implements PluginAPIInterface {
|
|||
* Called when the plugin is being unloaded
|
||||
*/
|
||||
cleanup(): void {
|
||||
Log.log(`Cleaning up PluginAPI for plugin ${this._pluginId}`);
|
||||
PluginLog.log(`Cleaning up PluginAPI for plugin ${this._pluginId}`);
|
||||
|
||||
// Clear all hook handlers
|
||||
this._hookHandlers.clear();
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import { isAllowedPluginAction } from './allowed-plugin-actions.const';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from '../t.const';
|
||||
import { SyncWrapperService } from '../imex/sync/sync-wrapper.service';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
/**
|
||||
* PluginBridge acts as an intermediary layer between plugins and the main application services.
|
||||
|
|
@ -120,7 +120,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
duration: 5000, // 5 seconds default duration
|
||||
});
|
||||
|
||||
Log.log('PluginBridge: Notification sent successfully', notifyCfg);
|
||||
PluginLog.log('PluginBridge: Notification sent successfully', notifyCfg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,11 +143,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
Log.log('PluginBridge: Dialog closed with result:', result);
|
||||
PluginLog.log('PluginBridge: Dialog closed with result:', result);
|
||||
resolve();
|
||||
});
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Failed to open dialog:', error);
|
||||
PluginLog.err('PluginBridge: Failed to open dialog:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
|
|
@ -164,7 +164,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._translateService.instant(T.PLUGINS.NO_PLUGIN_ID_PROVIDED_FOR_HTML),
|
||||
);
|
||||
}
|
||||
Log.log('PluginBridge: Navigating to plugin index view', {
|
||||
PluginLog.log('PluginBridge: Navigating to plugin index view', {
|
||||
pluginId: targetPluginId,
|
||||
});
|
||||
// Navigate to the plugin index route
|
||||
|
|
@ -195,12 +195,12 @@ export class PluginBridgeService implements OnDestroy {
|
|||
return task as TaskCopy;
|
||||
});
|
||||
|
||||
Log.log('PluginBridge: Retrieved archived tasks', {
|
||||
PluginLog.log('PluginBridge: Retrieved archived tasks', {
|
||||
count: archivedTasks.length,
|
||||
});
|
||||
return archivedTasks;
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Failed to load archived tasks:', error);
|
||||
PluginLog.err('PluginBridge: Failed to load archived tasks:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +232,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the task using TaskService (TaskCopy is compatible with Task)
|
||||
this._taskService.update(taskId, updates);
|
||||
|
||||
Log.log('PluginBridge: Task updated successfully', { taskId, updates });
|
||||
PluginLog.log('PluginBridge: Task updated successfully', { taskId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -270,7 +270,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
}),
|
||||
);
|
||||
|
||||
Log.log('PluginBridge: Subtask added successfully', {
|
||||
PluginLog.log('PluginBridge: Subtask added successfully', {
|
||||
taskId: task.id,
|
||||
taskData,
|
||||
});
|
||||
|
|
@ -293,7 +293,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
false, // isAddToBottom
|
||||
);
|
||||
|
||||
Log.log('PluginBridge: Task added successfully', { taskId, taskData });
|
||||
PluginLog.log('PluginBridge: Task added successfully', { taskId, taskData });
|
||||
return taskId;
|
||||
}
|
||||
}
|
||||
|
|
@ -312,7 +312,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
async addProject(projectData: Partial<ProjectCopy>): Promise<string> {
|
||||
typia.assert<Partial<ProjectCopy>>(projectData);
|
||||
|
||||
Log.log('PluginBridge: Project add', { projectData });
|
||||
PluginLog.log('PluginBridge: Project add', { projectData });
|
||||
return this._projectService.add(projectData);
|
||||
}
|
||||
|
||||
|
|
@ -326,7 +326,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the project using ProjectService (ProjectCopy is compatible with Project)
|
||||
this._projectService.update(projectId, updates);
|
||||
|
||||
Log.log('PluginBridge: Project updated successfully', { projectId, updates });
|
||||
PluginLog.log('PluginBridge: Project updated successfully', { projectId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -345,7 +345,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Add the tag using TagService (TagCopy is compatible with Tag)
|
||||
const tagId = this._tagService.addTag(tagData);
|
||||
Log.log('PluginBridge: Tag added successfully', { tagId, tagData });
|
||||
PluginLog.log('PluginBridge: Tag added successfully', { tagId, tagData });
|
||||
return tagId;
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +358,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Update the tag using TagService (TagCopy is compatible with Tag)
|
||||
this._tagService.updateTag(tagId, updates);
|
||||
Log.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
PluginLog.log('PluginBridge: Tag updated successfully', { tagId, updates });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -401,7 +401,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
allTasks?.filter((t) => t.projectId === contextId && !t.parentId) || [];
|
||||
const taskIdsInProject = tasksInProject.map((t) => t.id);
|
||||
|
||||
Log.log('PluginBridge: Validating task reorder', {
|
||||
PluginLog.log('PluginBridge: Validating task reorder', {
|
||||
requestedTaskIds: taskIds,
|
||||
projectTaskIds: allProjectTaskIds,
|
||||
actualTasksInProject: taskIdsInProject,
|
||||
|
|
@ -427,7 +427,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Note: This assumes all tasks are in the regular list, not backlog
|
||||
this._projectService.update(contextId, { taskIds });
|
||||
|
||||
Log.log('PluginBridge: Project tasks reordered successfully', {
|
||||
PluginLog.log('PluginBridge: Project tasks reordered successfully', {
|
||||
projectId: contextId,
|
||||
newOrder: taskIds,
|
||||
});
|
||||
|
|
@ -461,7 +461,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
// Update the task with new subtask order
|
||||
this._taskService.update(contextId, { subTaskIds: taskIds });
|
||||
|
||||
Log.log('PluginBridge: Subtasks reordered successfully', {
|
||||
PluginLog.log('PluginBridge: Subtasks reordered successfully', {
|
||||
parentTaskId: contextId,
|
||||
newOrder: taskIds,
|
||||
});
|
||||
|
|
@ -485,11 +485,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._currentPluginId,
|
||||
dataStr,
|
||||
);
|
||||
Log.log('PluginBridge: Plugin data persisted successfully', {
|
||||
PluginLog.log('PluginBridge: Plugin data persisted successfully', {
|
||||
pluginId: this._currentPluginId,
|
||||
});
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Failed to persist plugin data:', error);
|
||||
PluginLog.err('PluginBridge: Failed to persist plugin data:', error);
|
||||
throw new Error(this._translateService.instant(T.PLUGINS.UNABLE_TO_PERSIST_DATA));
|
||||
}
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._currentPluginId,
|
||||
);
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Failed to get persisted plugin data:', error);
|
||||
PluginLog.err('PluginBridge: Failed to get persisted plugin data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -523,11 +523,11 @@ export class PluginBridgeService implements OnDestroy {
|
|||
}
|
||||
|
||||
try {
|
||||
Log.log('PluginBridge: Triggering sync for plugin', this._currentPluginId);
|
||||
PluginLog.log('PluginBridge: Triggering sync for plugin', this._currentPluginId);
|
||||
await this._syncWrapperService.sync();
|
||||
Log.log('PluginBridge: Sync completed successfully');
|
||||
PluginLog.log('PluginBridge: Sync completed successfully');
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Sync failed:', error);
|
||||
PluginLog.err('PluginBridge: Sync failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -555,7 +555,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this._removePluginSidePanelButtons(pluginId);
|
||||
this.unregisterPluginShortcuts(pluginId);
|
||||
|
||||
Log.log('PluginBridge: All hooks unregistered for plugin', { pluginId });
|
||||
PluginLog.log('PluginBridge: All hooks unregistered for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -577,7 +577,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const currentButtons = this._headerButtons$.value;
|
||||
this._headerButtons$.next([...currentButtons, newButton]);
|
||||
|
||||
Log.log('PluginBridge: Header button registered', {
|
||||
PluginLog.log('PluginBridge: Header button registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
headerBtnCfg,
|
||||
});
|
||||
|
|
@ -622,16 +622,19 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
Log.err('PluginBridge: Duplicate menu entry detected, skipping registration', {
|
||||
pluginId: this._currentPluginId,
|
||||
label: menuEntryCfg.label,
|
||||
});
|
||||
PluginLog.err(
|
||||
'PluginBridge: Duplicate menu entry detected, skipping registration',
|
||||
{
|
||||
pluginId: this._currentPluginId,
|
||||
label: menuEntryCfg.label,
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this._menuEntries$.next([...currentEntries, newMenuEntry]);
|
||||
|
||||
Log.log('PluginBridge: Menu entry registered', {
|
||||
PluginLog.log('PluginBridge: Menu entry registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
menuEntryCfg,
|
||||
});
|
||||
|
|
@ -647,7 +650,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
this._headerButtons$.next(filteredButtons);
|
||||
|
||||
Log.log('PluginBridge: Header buttons removed for plugin', { pluginId });
|
||||
PluginLog.log('PluginBridge: Header buttons removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -658,7 +661,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const filteredEntries = currentEntries.filter((entry) => entry.pluginId !== pluginId);
|
||||
this._menuEntries$.next(filteredEntries);
|
||||
|
||||
Log.log('PluginBridge: Menu entries removed for plugin', { pluginId });
|
||||
PluginLog.log('PluginBridge: Menu entries removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -698,7 +701,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
|
||||
if (isDuplicate) {
|
||||
Log.err(
|
||||
PluginLog.err(
|
||||
'PluginBridge: Duplicate side panel button detected, skipping registration',
|
||||
{
|
||||
pluginId: this._currentPluginId,
|
||||
|
|
@ -710,7 +713,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
this._sidePanelButtons$.next([...currentButtons, newButton]);
|
||||
|
||||
Log.log('PluginBridge: Side panel button registered', {
|
||||
PluginLog.log('PluginBridge: Side panel button registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
sidePanelBtnCfg,
|
||||
});
|
||||
|
|
@ -726,7 +729,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
);
|
||||
this._sidePanelButtons$.next(filteredButtons);
|
||||
|
||||
Log.log('PluginBridge: Side panel buttons removed for plugin', { pluginId });
|
||||
PluginLog.log('PluginBridge: Side panel buttons removed for plugin', { pluginId });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -747,7 +750,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
const currentShortcuts = this.shortcuts$.value;
|
||||
this.shortcuts$.next([...currentShortcuts, shortcutWithPluginId]);
|
||||
|
||||
Log.log('PluginBridge: Shortcut registered', {
|
||||
PluginLog.log('PluginBridge: Shortcut registered', {
|
||||
pluginId: this._currentPluginId,
|
||||
shortcut: shortcutWithPluginId,
|
||||
});
|
||||
|
|
@ -763,10 +766,12 @@ export class PluginBridgeService implements OnDestroy {
|
|||
if (shortcut) {
|
||||
try {
|
||||
await Promise.resolve(shortcut.onExec());
|
||||
Log.log(`Executed shortcut "${shortcut.label}" from plugin ${shortcut.pluginId}`);
|
||||
PluginLog.log(
|
||||
`Executed shortcut "${shortcut.label}" from plugin ${shortcut.pluginId}`,
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
Log.err(`Failed to execute shortcut "${shortcut.label}":`, error);
|
||||
PluginLog.err(`Failed to execute shortcut "${shortcut.label}":`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -785,7 +790,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
if (filteredShortcuts.length !== currentShortcuts.length) {
|
||||
this.shortcuts$.next(filteredShortcuts);
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Unregistered ${currentShortcuts.length - filteredShortcuts.length} shortcuts for plugin ${pluginId}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -863,7 +868,9 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Check if the action is in the allowed list
|
||||
if (!isAllowedPluginAction(action)) {
|
||||
Log.err(`PluginBridge: Action type '${action.type}' is not allowed for plugins`);
|
||||
PluginLog.err(
|
||||
`PluginBridge: Action type '${action.type}' is not allowed for plugins`,
|
||||
);
|
||||
throw new Error(
|
||||
this._translateService.instant(T.PLUGINS.ACTION_TYPE_NOT_ALLOWED, {
|
||||
actionType: action.type,
|
||||
|
|
@ -873,7 +880,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
// Dispatch the action
|
||||
this._store.dispatch(action);
|
||||
Log.log(`PluginBridge: Dispatched action for plugin ${this._currentPluginId}`, {
|
||||
PluginLog.log(`PluginBridge: Dispatched action for plugin ${this._currentPluginId}`, {
|
||||
actionType: action.type,
|
||||
payload: action,
|
||||
});
|
||||
|
|
@ -926,7 +933,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
|
||||
return result;
|
||||
} catch (error) {
|
||||
Log.err('PluginBridge: Failed to execute Node.js script:', error);
|
||||
PluginLog.err('PluginBridge: Failed to execute Node.js script:', error);
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
|
|
@ -952,7 +959,7 @@ export class PluginBridgeService implements OnDestroy {
|
|||
* Clean up all resources when service is destroyed
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
Log.log('PluginBridgeService: Cleaning up resources');
|
||||
PluginLog.log('PluginBridgeService: Cleaning up resources');
|
||||
|
||||
// Complete all BehaviorSubjects
|
||||
this._headerButtons$.complete();
|
||||
|
|
@ -960,6 +967,6 @@ export class PluginBridgeService implements OnDestroy {
|
|||
this.shortcuts$.complete();
|
||||
this._sidePanelButtons$.complete();
|
||||
|
||||
Log.log('PluginBridgeService: Cleanup complete');
|
||||
PluginLog.log('PluginBridgeService: Cleanup complete');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
export interface CachedPlugin {
|
||||
id: string;
|
||||
|
|
@ -65,18 +65,19 @@ export class PluginCacheService {
|
|||
};
|
||||
const totalSizeKB = Object.values(sizes).reduce((sum, size) => sum + size, 0);
|
||||
|
||||
Log.log(`[PluginCache] Storing plugin "${pluginId}":`);
|
||||
Log.log(`[PluginCache] - Manifest: ${sizes.manifest.toFixed(2)}KB`);
|
||||
Log.log(`[PluginCache] - Code: ${sizes.code.toFixed(2)}KB`);
|
||||
if (indexHtml) Log.log(`[PluginCache] - IndexHtml: ${sizes.indexHtml.toFixed(2)}KB`);
|
||||
if (icon) Log.log(`[PluginCache] - Icon: ${sizes.icon.toFixed(2)}KB`);
|
||||
Log.log(
|
||||
PluginLog.log(`[PluginCache] Storing plugin "${pluginId}":`);
|
||||
PluginLog.log(`[PluginCache] - Manifest: ${sizes.manifest.toFixed(2)}KB`);
|
||||
PluginLog.log(`[PluginCache] - Code: ${sizes.code.toFixed(2)}KB`);
|
||||
if (indexHtml)
|
||||
PluginLog.log(`[PluginCache] - IndexHtml: ${sizes.indexHtml.toFixed(2)}KB`);
|
||||
if (icon) PluginLog.log(`[PluginCache] - Icon: ${sizes.icon.toFixed(2)}KB`);
|
||||
PluginLog.log(
|
||||
`[PluginCache] - Total size: ${totalSizeKB.toFixed(2)}KB (${(totalSizeKB / 1024).toFixed(2)}MB)`,
|
||||
);
|
||||
|
||||
if (totalSizeKB > 1024) {
|
||||
// Warn if plugin is larger than 1MB
|
||||
Log.err(
|
||||
PluginLog.err(
|
||||
`[PluginCache] Large plugin detected: "${pluginId}" is ${(totalSizeKB / 1024).toFixed(2)}MB`,
|
||||
);
|
||||
}
|
||||
|
|
@ -97,11 +98,14 @@ export class PluginCacheService {
|
|||
return new Promise((resolve, reject) => {
|
||||
const request = store.put(plugin);
|
||||
request.onsuccess = () => {
|
||||
Log.log(`[PluginCache] Successfully stored plugin "${pluginId}"`);
|
||||
PluginLog.log(`[PluginCache] Successfully stored plugin "${pluginId}"`);
|
||||
resolve();
|
||||
};
|
||||
request.onerror = () => {
|
||||
Log.err(`[PluginCache] Failed to store plugin "${pluginId}":`, request.error);
|
||||
PluginLog.err(
|
||||
`[PluginCache] Failed to store plugin "${pluginId}":`,
|
||||
request.error,
|
||||
);
|
||||
reject(new Error(`Failed to store plugin ${pluginId}`));
|
||||
};
|
||||
});
|
||||
|
|
@ -111,7 +115,7 @@ export class PluginCacheService {
|
|||
* Get a plugin from the cache
|
||||
*/
|
||||
async getPlugin(pluginId: string): Promise<CachedPlugin | null> {
|
||||
Log.log(`[PluginCache] Loading plugin "${pluginId}"`);
|
||||
PluginLog.log(`[PluginCache] Loading plugin "${pluginId}"`);
|
||||
const db = await this._getDB();
|
||||
const transaction = db.transaction([this.STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
|
|
@ -142,7 +146,7 @@ export class PluginCacheService {
|
|||
* Get all cached plugins
|
||||
*/
|
||||
async getAllPlugins(): Promise<CachedPlugin[]> {
|
||||
Log.log('[PluginCache] Loading all plugins from cache');
|
||||
PluginLog.log('[PluginCache] Loading all plugins from cache');
|
||||
const db = await this._getDB();
|
||||
const transaction = db.transaction([this.STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Hooks, PluginHookHandler } from './plugin-api.model';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin hooks service following KISS principles.
|
||||
|
|
@ -20,7 +20,7 @@ export class PluginHooksService {
|
|||
this._handlers.set(hook, new Map());
|
||||
}
|
||||
this._handlers.get(hook)!.set(pluginId, handler);
|
||||
Log.log(`Plugin ${pluginId} registered for ${hook}`);
|
||||
PluginLog.log(`Plugin ${pluginId} registered for ${hook}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -37,7 +37,7 @@ export class PluginHooksService {
|
|||
try {
|
||||
await handler(payload);
|
||||
} catch (error) {
|
||||
Log.err(`Plugin ${pluginId} ${hook} handler error:`, error);
|
||||
PluginLog.err(`Plugin ${pluginId} ${hook} handler error:`, error);
|
||||
// Continue with other handlers
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { PluginManifest } from './plugin-api.model';
|
|||
import { PluginCacheService } from './plugin-cache.service';
|
||||
// KISS: No size checks in loader - trust the browser's limits
|
||||
import { validatePluginManifest } from './util/validate-manifest.util';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
interface PluginAssets {
|
||||
manifest: PluginManifest;
|
||||
|
|
@ -70,7 +70,7 @@ export class PluginLoaderService {
|
|||
.pipe(first())
|
||||
.toPromise();
|
||||
} catch (e) {
|
||||
Log.err(`No index.html for plugin ${manifest.id}`);
|
||||
PluginLog.err(`No index.html for plugin ${manifest.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,13 +82,13 @@ export class PluginLoaderService {
|
|||
.pipe(first())
|
||||
.toPromise();
|
||||
} catch (e) {
|
||||
Log.err(`No icon for plugin ${manifest.id}`);
|
||||
PluginLog.err(`No icon for plugin ${manifest.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
return { manifest, code, indexHtml, icon };
|
||||
} catch (error) {
|
||||
Log.err(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
PluginLog.err(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { inject, Injectable } from '@angular/core';
|
||||
import { PfapiService } from '../pfapi/pfapi.service';
|
||||
import { PluginMetadata, PluginMetaDataState } from './plugin-persistence.model';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
/**
|
||||
* Service for persisting plugin metadata using pfapi.
|
||||
|
|
@ -28,7 +28,7 @@ export class PluginMetaPersistenceService {
|
|||
|
||||
// Deep compare the states
|
||||
if (this._isDataEqual(currentState, newState)) {
|
||||
Log.log('PluginMetaPersistenceService: No changes detected, skipping write');
|
||||
PluginLog.log('PluginMetaPersistenceService: No changes detected, skipping write');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ export class PluginMetaPersistenceService {
|
|||
await this._pfapiService.pf.m.pluginMetadata.save(newState, {
|
||||
isUpdateRevAndLastUpdate: true,
|
||||
});
|
||||
Log.log('PluginMetaPersistenceService: Data updated');
|
||||
PluginLog.log('PluginMetaPersistenceService: Data updated');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { PluginSecurityService } from './plugin-security';
|
|||
import { SnackService } from '../core/snack/snack.service';
|
||||
import { IS_ELECTRON } from '../app.constants';
|
||||
import { PluginCleanupService } from './plugin-cleanup.service';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin runner following KISS principles.
|
||||
|
|
@ -59,7 +59,7 @@ export class PluginRunner {
|
|||
|
||||
// Show warnings if any
|
||||
if (analysis.warnings.length > 0) {
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, analysis.warnings);
|
||||
PluginLog.err(`Plugin ${manifest.id} warnings:`, analysis.warnings);
|
||||
this._snackService.open({
|
||||
msg: `Plugin "${manifest.name}" has warnings: ${analysis.warnings[0]}`,
|
||||
type: 'CUSTOM',
|
||||
|
|
@ -69,7 +69,7 @@ export class PluginRunner {
|
|||
|
||||
// Log info for transparency
|
||||
if (analysis.info.length > 0) {
|
||||
Log.info(`Plugin ${manifest.id} info:`, analysis.info);
|
||||
PluginLog.info(`Plugin ${manifest.id} info:`, analysis.info);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -102,13 +102,13 @@ export class PluginRunner {
|
|||
} catch (error) {
|
||||
pluginInstance.error =
|
||||
error instanceof Error ? error.message : 'Failed to load plugin';
|
||||
Log.err(`Plugin ${manifest.id} error:`, error);
|
||||
PluginLog.err(`Plugin ${manifest.id} error:`, error);
|
||||
}
|
||||
|
||||
this._loadedPlugins.set(manifest.id, pluginInstance);
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
Log.err(`Failed to load plugin ${manifest.id}:`, error);
|
||||
PluginLog.err(`Failed to load plugin ${manifest.id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -173,7 +173,7 @@ export class PluginRunner {
|
|||
// Unregister hooks
|
||||
this._pluginBridge.unregisterPluginHooks(pluginId);
|
||||
|
||||
Log.log(`Plugin ${pluginId} unloaded`);
|
||||
PluginLog.log(`Plugin ${pluginId} unloaded`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import { PluginLoaderService } from './plugin-loader.service';
|
|||
import { validatePluginManifest } from './util/validate-manifest.util';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from '../t.const';
|
||||
import { Log } from '../core/log';
|
||||
import { PluginLog } from '../core/log';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
@ -67,11 +67,11 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
async initializePlugins(): Promise<void> {
|
||||
if (this._isInitialized) {
|
||||
Log.err(this._translateService.instant(T.PLUGINS.ALREADY_INITIALIZED));
|
||||
PluginLog.err(this._translateService.instant(T.PLUGINS.ALREADY_INITIALIZED));
|
||||
return;
|
||||
}
|
||||
|
||||
Log.log('Initializing plugin system...');
|
||||
PluginLog.log('Initializing plugin system...');
|
||||
|
||||
try {
|
||||
// Only load manifests, not the actual plugin code
|
||||
|
|
@ -82,9 +82,9 @@ export class PluginService implements OnDestroy {
|
|||
await this._loadEnabledPlugins();
|
||||
|
||||
this._isInitialized = true;
|
||||
Log.log('Plugin system initialized successfully');
|
||||
PluginLog.log('Plugin system initialized successfully');
|
||||
} catch (error) {
|
||||
Log.err('Failed to initialize plugin system:', error);
|
||||
PluginLog.err('Failed to initialize plugin system:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -132,13 +132,13 @@ export class PluginService implements OnDestroy {
|
|||
}
|
||||
} catch (e) {
|
||||
// Icon is optional - silently ignore 404s and other errors
|
||||
Log.debug(
|
||||
PluginLog.debug(
|
||||
`Icon not found for plugin ${manifest.id}: ${path}/${manifest.icon || 'icon.svg'}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
Log.err(`Failed to discover plugin at ${path}:`, error);
|
||||
PluginLog.err(`Failed to discover plugin at ${path}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,13 +187,13 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginIcons.set(cachedPlugin.id, cachedPlugin.icon);
|
||||
}
|
||||
} catch (error) {
|
||||
Log.err(`Failed to discover cached plugin ${cachedPlugin.id}:`, error);
|
||||
PluginLog.err(`Failed to discover cached plugin ${cachedPlugin.id}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
this._updatePluginStates();
|
||||
} catch (error) {
|
||||
Log.err('Failed to discover cached plugins:', error);
|
||||
PluginLog.err('Failed to discover cached plugins:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,11 +203,11 @@ export class PluginService implements OnDestroy {
|
|||
(state) => state.isEnabled,
|
||||
);
|
||||
|
||||
Log.log(`Loading ${pluginsToLoad.length} enabled plugins...`);
|
||||
PluginLog.log(`Loading ${pluginsToLoad.length} enabled plugins...`);
|
||||
|
||||
// Log which plugins are being loaded
|
||||
for (const state of pluginsToLoad) {
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Loading plugin: ${state.manifest.id} (enabled: ${state.isEnabled}, hooks: ${state.manifest.hooks?.length || 0}, sidePanel: ${state.manifest.sidePanel})`,
|
||||
);
|
||||
}
|
||||
|
|
@ -228,7 +228,7 @@ export class PluginService implements OnDestroy {
|
|||
async activatePlugin(pluginId: string): Promise<PluginInstance | null> {
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
Log.err(`Plugin ${pluginId} not found`);
|
||||
PluginLog.err(`Plugin ${pluginId} not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ export class PluginService implements OnDestroy {
|
|||
this._updatePluginStates();
|
||||
|
||||
try {
|
||||
Log.log(`Activating plugin: ${pluginId}`);
|
||||
PluginLog.log(`Activating plugin: ${pluginId}`);
|
||||
const instance = await this._loadPluginLazy(state);
|
||||
|
||||
state.status = 'loaded';
|
||||
|
|
@ -273,7 +273,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
return instance;
|
||||
} catch (error) {
|
||||
Log.err(`Failed to activate plugin ${pluginId}:`, error);
|
||||
PluginLog.err(`Failed to activate plugin ${pluginId}:`, error);
|
||||
state.status = 'error';
|
||||
state.error = error instanceof Error ? error.message : String(error);
|
||||
this._updatePluginStates();
|
||||
|
|
@ -311,7 +311,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
const promises = cachedPlugins.map(async (cachedPlugin) => {
|
||||
try {
|
||||
Log.log(`Loading cached plugin: ${cachedPlugin.id}`);
|
||||
PluginLog.log(`Loading cached plugin: ${cachedPlugin.id}`);
|
||||
// Set the path for reload functionality
|
||||
this._pluginPaths.set(cachedPlugin.id, `uploaded://${cachedPlugin.id}`);
|
||||
|
||||
|
|
@ -319,14 +319,14 @@ export class PluginService implements OnDestroy {
|
|||
await this._loadUploadedPlugin(cachedPlugin.id);
|
||||
// The plugin instance is already added to _loadedPlugins in _loadUploadedPlugin if loaded successfully
|
||||
} catch (error) {
|
||||
Log.err(`Failed to load cached plugin ${cachedPlugin.id}:`, error);
|
||||
PluginLog.err(`Failed to load cached plugin ${cachedPlugin.id}:`, error);
|
||||
// Continue loading other plugins even if one fails
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.allSettled(promises);
|
||||
} catch (error) {
|
||||
Log.err('Failed to load cached plugins:', error);
|
||||
PluginLog.err('Failed to load cached plugins:', error);
|
||||
// Don't throw - this shouldn't prevent other plugins from loading
|
||||
}
|
||||
}
|
||||
|
|
@ -351,9 +351,9 @@ export class PluginService implements OnDestroy {
|
|||
if (pluginInstance.manifest && pluginInstance.manifest.id) {
|
||||
this._pluginPaths.set(pluginInstance.manifest.id, pluginPath);
|
||||
}
|
||||
Log.log(`${type} plugin loaded successfully from ${pluginPath}`);
|
||||
PluginLog.log(`${type} plugin loaded successfully from ${pluginPath}`);
|
||||
} catch (error) {
|
||||
Log.err(`Failed to load ${type} plugin from ${pluginPath}:`, error);
|
||||
PluginLog.err(`Failed to load ${type} plugin from ${pluginPath}:`, error);
|
||||
// Continue loading other plugins even if one fails
|
||||
}
|
||||
});
|
||||
|
|
@ -402,7 +402,9 @@ export class PluginService implements OnDestroy {
|
|||
error: this._translateService.instant(T.PLUGINS.NODE_ONLY_DESKTOP),
|
||||
};
|
||||
this._pluginPaths.set(manifest.id, pluginPath); // Store the path for potential reload
|
||||
Log.log(`Plugin ${manifest.id} requires desktop version, creating placeholder`);
|
||||
PluginLog.log(
|
||||
`Plugin ${manifest.id} requires desktop version, creating placeholder`,
|
||||
);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -420,10 +422,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
PluginLog.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
PluginLog.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// If plugin is disabled, create a placeholder instance without loading code
|
||||
|
|
@ -435,7 +437,7 @@ export class PluginService implements OnDestroy {
|
|||
error: undefined,
|
||||
};
|
||||
this._pluginPaths.set(manifest.id, pluginPath); // Store the path for potential reload
|
||||
Log.log(`Plugin ${manifest.id} is disabled, skipping load`);
|
||||
PluginLog.log(`Plugin ${manifest.id} is disabled, skipping load`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -465,14 +467,14 @@ export class PluginService implements OnDestroy {
|
|||
// The enabled state will be persisted later when user explicitly enables/disables plugins
|
||||
this._ensurePluginEnabledInMemory(manifest.id);
|
||||
|
||||
Log.log(`Plugin ${manifest.id} loaded successfully`);
|
||||
PluginLog.log(`Plugin ${manifest.id} loaded successfully`);
|
||||
} else {
|
||||
Log.err(`Plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
PluginLog.err(`Plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
}
|
||||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
Log.err(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
PluginLog.err(`Failed to load plugin from ${pluginPath}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -617,7 +619,7 @@ export class PluginService implements OnDestroy {
|
|||
// Check if plugin exists in states
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
Log.err(`Plugin ${pluginId} not found`);
|
||||
PluginLog.err(`Plugin ${pluginId} not found`);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
return;
|
||||
}
|
||||
|
|
@ -634,11 +636,11 @@ export class PluginService implements OnDestroy {
|
|||
if (instance) {
|
||||
this._activeSidePanelPlugin$.next(instance);
|
||||
} else {
|
||||
Log.err(`Failed to activate plugin ${pluginId}`);
|
||||
PluginLog.err(`Failed to activate plugin ${pluginId}`);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
}
|
||||
} catch (error) {
|
||||
Log.err(`Error activating plugin ${pluginId}:`, error);
|
||||
PluginLog.err(`Error activating plugin ${pluginId}:`, error);
|
||||
this._activeSidePanelPlugin$.next(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -701,7 +703,7 @@ export class PluginService implements OnDestroy {
|
|||
}
|
||||
|
||||
async loadPluginFromZip(file: File): Promise<PluginInstance> {
|
||||
Log.log(`Starting plugin load from ZIP: ${file.name}`);
|
||||
PluginLog.log(`Starting plugin load from ZIP: ${file.name}`);
|
||||
|
||||
// Import fflate dynamically for better bundle size
|
||||
const { unzip } = await import('fflate');
|
||||
|
|
@ -739,7 +741,7 @@ export class PluginService implements OnDestroy {
|
|||
});
|
||||
},
|
||||
);
|
||||
Log.log({ extractedFiles });
|
||||
PluginLog.log({ extractedFiles });
|
||||
|
||||
// Find and extract manifest.json
|
||||
if (!extractedFiles['manifest.json']) {
|
||||
|
|
@ -820,7 +822,7 @@ export class PluginService implements OnDestroy {
|
|||
iconContent = new TextDecoder().decode(iconBytes);
|
||||
// Basic SVG validation
|
||||
if (!iconContent.includes('<svg') || !iconContent.includes('</svg>')) {
|
||||
Log.err(`Plugin icon ${manifest.icon} does not appear to be a valid SVG`);
|
||||
PluginLog.err(`Plugin icon ${manifest.icon} does not appear to be a valid SVG`);
|
||||
iconContent = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -828,10 +830,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
PluginLog.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
PluginLog.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// Check if plugin is enabled (default to true for new uploads)
|
||||
|
|
@ -896,7 +898,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Uploaded plugin ${manifest.id} requires desktop version, creating placeholder`,
|
||||
);
|
||||
return placeholderInstance;
|
||||
|
|
@ -934,7 +936,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
Log.log(`Uploaded plugin ${manifest.id} is disabled, skipping load`);
|
||||
PluginLog.log(`Uploaded plugin ${manifest.id} is disabled, skipping load`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -973,9 +975,12 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.set(manifest.id, state);
|
||||
this._updatePluginStates();
|
||||
|
||||
Log.log(`Uploaded plugin ${manifest.id} loaded successfully`);
|
||||
PluginLog.log(`Uploaded plugin ${manifest.id} loaded successfully`);
|
||||
} else {
|
||||
Log.err(`Uploaded plugin ${manifest.id} failed to load:`, pluginInstance.error);
|
||||
PluginLog.err(
|
||||
`Uploaded plugin ${manifest.id} failed to load:`,
|
||||
pluginInstance.error,
|
||||
);
|
||||
|
||||
// Add failed plugin to states as well
|
||||
const state: PluginState = {
|
||||
|
|
@ -993,7 +998,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
Log.err('Failed to load plugin from ZIP:', error);
|
||||
PluginLog.err('Failed to load plugin from ZIP:', error);
|
||||
|
||||
// Create error instance for UI display
|
||||
const errorInstance: PluginInstance = {
|
||||
|
|
@ -1067,7 +1072,7 @@ export class PluginService implements OnDestroy {
|
|||
this._pluginStates.delete(pluginId);
|
||||
this._updatePluginStates();
|
||||
|
||||
Log.log(`Uploaded plugin ${pluginId} removed completely`);
|
||||
PluginLog.log(`Uploaded plugin ${pluginId} removed completely`);
|
||||
}
|
||||
|
||||
unloadPlugin(pluginId: string): boolean {
|
||||
|
|
@ -1106,7 +1111,7 @@ export class PluginService implements OnDestroy {
|
|||
// In lazy loading mode, unload and re-activate
|
||||
const state = this._pluginStates.get(pluginId);
|
||||
if (!state) {
|
||||
Log.err(`Cannot reload plugin ${pluginId}: not found`);
|
||||
PluginLog.err(`Cannot reload plugin ${pluginId}: not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1146,10 +1151,10 @@ export class PluginService implements OnDestroy {
|
|||
// Analyze plugin code (informational only - KISS approach)
|
||||
const codeAnalysis = this._pluginSecurity.analyzePluginCode(pluginCode, manifest);
|
||||
if (codeAnalysis.warnings.length > 0) {
|
||||
Log.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
PluginLog.err(`Plugin ${manifest.id} warnings:`, codeAnalysis.warnings);
|
||||
}
|
||||
if (codeAnalysis.info.length > 0) {
|
||||
Log.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
PluginLog.info(`Plugin ${manifest.id} info:`, codeAnalysis.info);
|
||||
}
|
||||
|
||||
// Check if plugin is enabled
|
||||
|
|
@ -1165,7 +1170,7 @@ export class PluginService implements OnDestroy {
|
|||
isEnabled: false,
|
||||
error: undefined,
|
||||
};
|
||||
Log.log(`Uploaded plugin ${manifest.id} is disabled, skipping reload`);
|
||||
PluginLog.log(`Uploaded plugin ${manifest.id} is disabled, skipping reload`);
|
||||
return placeholderInstance;
|
||||
}
|
||||
|
||||
|
|
@ -1189,14 +1194,17 @@ export class PluginService implements OnDestroy {
|
|||
// Replace existing instance
|
||||
this._loadedPlugins[existingIndex] = pluginInstance;
|
||||
}
|
||||
Log.log(`Uploaded plugin ${manifest.id} reloaded successfully`);
|
||||
PluginLog.log(`Uploaded plugin ${manifest.id} reloaded successfully`);
|
||||
} else {
|
||||
Log.err(`Uploaded plugin ${manifest.id} failed to reload:`, pluginInstance.error);
|
||||
PluginLog.err(
|
||||
`Uploaded plugin ${manifest.id} failed to reload:`,
|
||||
pluginInstance.error,
|
||||
);
|
||||
}
|
||||
|
||||
return pluginInstance;
|
||||
} catch (error) {
|
||||
Log.err(`Failed to reload uploaded plugin ${pluginId}:`, error);
|
||||
PluginLog.err(`Failed to reload uploaded plugin ${pluginId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -1212,7 +1220,7 @@ export class PluginService implements OnDestroy {
|
|||
|
||||
// Only check consent in Electron environment
|
||||
if (!IS_ELECTRON) {
|
||||
Log.err(
|
||||
PluginLog.err(
|
||||
`Plugin ${manifest.id} requires nodeExecution permission which is not available in web environment`,
|
||||
);
|
||||
return false;
|
||||
|
|
@ -1269,13 +1277,13 @@ export class PluginService implements OnDestroy {
|
|||
private _ensurePluginEnabledInMemory(pluginId: string): void {
|
||||
// We only need to track this in memory for startup purposes
|
||||
// The actual persistence will happen when user explicitly enables/disables plugins
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Plugin ${pluginId} marked as enabled in memory (no pfapi write during startup)`,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
Log.log('PluginService: Cleaning up all resources');
|
||||
PluginLog.log('PluginService: Cleaning up all resources');
|
||||
|
||||
// Complete the side panel subject
|
||||
this._activeSidePanelPlugin$.complete();
|
||||
|
|
@ -1286,7 +1294,7 @@ export class PluginService implements OnDestroy {
|
|||
try {
|
||||
this.unloadPlugin(pluginId);
|
||||
} catch (error) {
|
||||
Log.err(`Error unloading plugin ${pluginId} during cleanup:`, error);
|
||||
PluginLog.err(`Error unloading plugin ${pluginId} during cleanup:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1302,6 +1310,6 @@ export class PluginService implements OnDestroy {
|
|||
// Clear loader caches
|
||||
this._pluginLoader.clearAllCaches();
|
||||
|
||||
Log.log('PluginService: Cleanup complete');
|
||||
PluginLog.log('PluginService: Cleanup complete');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { DialogButtonCfg, DialogCfg } from '../../plugin-api.model';
|
|||
import { PluginSecurityService } from '../../plugin-security';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { T } from '../../../t.const';
|
||||
import { Log } from '../../../core/log';
|
||||
import { PluginLog } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'plugin-dialog',
|
||||
|
|
@ -115,7 +115,7 @@ export class PluginDialogComponent {
|
|||
this._dialogRef.close(button.label);
|
||||
}
|
||||
} catch (error) {
|
||||
Log.err('Plugin dialog button action failed:', error);
|
||||
PluginLog.err('Plugin dialog button action failed:', error);
|
||||
this._dialogRef.close('error');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import {
|
|||
} from '@angular/material/card';
|
||||
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
||||
import { T } from '../../../t.const';
|
||||
import { Log } from '../../../core/log';
|
||||
import { PluginLog } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'plugin-index',
|
||||
|
|
@ -103,7 +103,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._loadPluginIndex(this.directPluginId);
|
||||
} catch (err) {
|
||||
Log.err('Failed to load plugin index:', err);
|
||||
PluginLog.err('Failed to load plugin index:', err);
|
||||
this.error.set(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
|
|
@ -117,7 +117,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
// Subscribe to route parameter changes to handle navigation between plugins
|
||||
this._routeSubscription = this._route.paramMap.subscribe(async (params) => {
|
||||
const newPluginId = params.get('pluginId');
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
'Route paramMap changed, newPluginId:',
|
||||
newPluginId,
|
||||
'currentPluginId:',
|
||||
|
|
@ -132,11 +132,13 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
|
||||
// Skip if it's the same plugin (prevent unnecessary reloads)
|
||||
if (this.pluginId() === newPluginId) {
|
||||
Log.log('Same plugin ID, skipping reload');
|
||||
PluginLog.log('Same plugin ID, skipping reload');
|
||||
return;
|
||||
}
|
||||
|
||||
Log.log(`Navigating from plugin "${this.pluginId()}" to plugin "${newPluginId}"`);
|
||||
PluginLog.log(
|
||||
`Navigating from plugin "${this.pluginId()}" to plugin "${newPluginId}"`,
|
||||
);
|
||||
|
||||
// Clean up previous iframe communication BEFORE setting new plugin ID
|
||||
this._cleanupIframeCommunication();
|
||||
|
|
@ -152,7 +154,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._loadPluginIndex(newPluginId);
|
||||
} catch (err) {
|
||||
Log.err('Failed to load plugin index:', err);
|
||||
PluginLog.err('Failed to load plugin index:', err);
|
||||
this.error.set(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
|
|
@ -170,7 +172,7 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
try {
|
||||
await this._pluginService.initializePlugins();
|
||||
} catch (error) {
|
||||
Log.err('Failed to initialize plugin system:', error);
|
||||
PluginLog.err('Failed to initialize plugin system:', error);
|
||||
throw new Error(
|
||||
this._translateService.instant(T.PLUGINS.PLUGIN_SYSTEM_FAILED_INIT),
|
||||
);
|
||||
|
|
@ -190,12 +192,12 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
private async _loadPluginIndex(pluginId: string): Promise<void> {
|
||||
Log.log(`Loading plugin index for: ${pluginId}`);
|
||||
PluginLog.log(`Loading plugin index for: ${pluginId}`);
|
||||
|
||||
// Get the plugin index.html content
|
||||
const indexContent = this._pluginService.getPluginIndexHtml(pluginId);
|
||||
if (!indexContent) {
|
||||
Log.err(`No index.html content found for plugin: ${pluginId}`);
|
||||
PluginLog.err(`No index.html content found for plugin: ${pluginId}`);
|
||||
// Try to get the plugin instance to check if it should have an index.html
|
||||
const plugins = await this._pluginService.getAllPlugins();
|
||||
const plugin = plugins.find((p) => p.manifest.id === pluginId);
|
||||
|
|
@ -244,30 +246,30 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
|
||||
// Create safe URL and set iframe source
|
||||
const safeUrl = this._sanitizer.bypassSecurityTrustResourceUrl(iframeUrl);
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
`Setting iframe src for plugin ${pluginId}:`,
|
||||
iframeUrl.substring(0, 100) + '...',
|
||||
);
|
||||
this.iframeSrc.set(safeUrl);
|
||||
this.isLoading.set(false);
|
||||
Log.log(`Plugin ${pluginId} iframe src set, loading complete`);
|
||||
PluginLog.log(`Plugin ${pluginId} iframe src set, loading complete`);
|
||||
}
|
||||
|
||||
private _cleanupIframeCommunication(): void {
|
||||
const currentPluginId = this.pluginId();
|
||||
Log.log(`Cleaning up iframe communication for plugin: ${currentPluginId}`);
|
||||
PluginLog.log(`Cleaning up iframe communication for plugin: ${currentPluginId}`);
|
||||
|
||||
// Remove message listener
|
||||
if (this._messageListener) {
|
||||
window.removeEventListener('message', this._messageListener);
|
||||
this._messageListener = undefined;
|
||||
Log.log(`Removed message listener for plugin: ${currentPluginId}`);
|
||||
PluginLog.log(`Removed message listener for plugin: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
// Clear iframe reference from cleanup service (but don't remove from DOM)
|
||||
if (currentPluginId) {
|
||||
this._cleanupService.cleanupPlugin(currentPluginId);
|
||||
Log.log(`Cleaned up plugin references for: ${currentPluginId}`);
|
||||
PluginLog.log(`Cleaned up plugin references for: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
// Set iframe to empty data URL to stop execution but keep iframe in DOM
|
||||
|
|
@ -276,11 +278,11 @@ export class PluginIndexComponent implements OnInit, OnDestroy {
|
|||
'data:text/html,<html><body></body></html>',
|
||||
),
|
||||
);
|
||||
Log.log(`Set iframe to empty data URL for plugin: ${currentPluginId}`);
|
||||
PluginLog.log(`Set iframe to empty data URL for plugin: ${currentPluginId}`);
|
||||
}
|
||||
|
||||
onIframeLoad(): void {
|
||||
Log.log('Plugin iframe loaded for plugin:', this.pluginId());
|
||||
PluginLog.log('Plugin iframe loaded for plugin:', this.pluginId());
|
||||
|
||||
// Register iframe with cleanup service
|
||||
if (this.iframeRef?.nativeElement && this.pluginId()) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import { PluginIconComponent } from '../plugin-icon/plugin-icon.component';
|
|||
import { IS_ELECTRON } from '../../../app.constants';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { DestroyRef } from '@angular/core';
|
||||
import { Log } from '../../../core/log';
|
||||
import { PluginLog } from '../../../core/log';
|
||||
|
||||
@Component({
|
||||
selector: 'plugin-management',
|
||||
|
|
@ -139,7 +139,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
}
|
||||
|
||||
private async enablePlugin(plugin: PluginInstance): Promise<void> {
|
||||
Log.log('Enabling plugin:', plugin.manifest.id);
|
||||
PluginLog.log('Enabling plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
// Check if plugin requires Node.js execution consent
|
||||
|
|
@ -147,7 +147,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
plugin.manifest,
|
||||
);
|
||||
if (!hasConsent) {
|
||||
Log.log(
|
||||
PluginLog.log(
|
||||
'User denied Node.js execution permission for plugin:',
|
||||
plugin.manifest.id,
|
||||
);
|
||||
|
|
@ -165,18 +165,18 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Activate the plugin (lazy load if needed)
|
||||
const instance = await this._pluginService.activatePlugin(plugin.manifest.id);
|
||||
if (instance) {
|
||||
Log.log('Plugin activated successfully:', plugin.manifest.id);
|
||||
PluginLog.log('Plugin activated successfully:', plugin.manifest.id);
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
await this.loadPlugins();
|
||||
} catch (error) {
|
||||
Log.err('Failed to enable plugin:', error);
|
||||
PluginLog.err('Failed to enable plugin:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private async disablePlugin(plugin: PluginInstance): Promise<void> {
|
||||
Log.log('Disabling plugin:', plugin.manifest.id);
|
||||
PluginLog.log('Disabling plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
// Set plugin as disabled in persistence
|
||||
|
|
@ -195,22 +195,22 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Reload plugins to get the updated state from the service
|
||||
await this.loadPlugins();
|
||||
} catch (error) {
|
||||
Log.err('Failed to disable plugin:', error);
|
||||
PluginLog.err('Failed to disable plugin:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async reloadPlugin(plugin: PluginInstance): Promise<void> {
|
||||
Log.log('Reloading plugin:', plugin.manifest.id);
|
||||
PluginLog.log('Reloading plugin:', plugin.manifest.id);
|
||||
|
||||
try {
|
||||
const success = await this._pluginService.reloadPlugin(plugin.manifest.id);
|
||||
if (success) {
|
||||
Log.log('Plugin reloaded successfully:', plugin.manifest.id);
|
||||
PluginLog.log('Plugin reloaded successfully:', plugin.manifest.id);
|
||||
} else {
|
||||
Log.err('Failed to reload plugin:', plugin.manifest.id);
|
||||
PluginLog.err('Failed to reload plugin:', plugin.manifest.id);
|
||||
}
|
||||
} catch (error) {
|
||||
Log.err('Failed to reload plugin:', error);
|
||||
PluginLog.err('Failed to reload plugin:', error);
|
||||
}
|
||||
|
||||
// Refresh the UI
|
||||
|
|
@ -299,7 +299,7 @@ export class PluginManagementComponent implements OnInit {
|
|||
// Clear the input
|
||||
input.value = '';
|
||||
} catch (error) {
|
||||
Log.err('Failed to load plugin from ZIP:', error);
|
||||
PluginLog.err('Failed to load plugin from ZIP:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
@ -318,9 +318,9 @@ export class PluginManagementComponent implements OnInit {
|
|||
await this._pluginCacheService.clearCache();
|
||||
await this.loadPlugins(); // Refresh the plugin list
|
||||
|
||||
Log.log('Plugin cache cleared successfully');
|
||||
PluginLog.log('Plugin cache cleared successfully');
|
||||
} catch (error) {
|
||||
Log.err('Failed to clear plugin cache:', error);
|
||||
PluginLog.err('Failed to clear plugin cache:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
@ -358,9 +358,9 @@ export class PluginManagementComponent implements OnInit {
|
|||
await this._pluginService.removeUploadedPlugin(plugin.manifest.id);
|
||||
await this.loadPlugins(); // Refresh the plugin list
|
||||
|
||||
Log.log(`Plugin ${plugin.manifest.id} removed successfully`);
|
||||
PluginLog.log(`Plugin ${plugin.manifest.id} removed successfully`);
|
||||
} catch (error) {
|
||||
Log.err('Failed to remove plugin:', error);
|
||||
PluginLog.err('Failed to remove plugin:', error);
|
||||
this.uploadError.set(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { Store } from '@ngrx/store';
|
|||
import { selectActivePluginId } from '../../../core-ui/layout/store/layout.reducer';
|
||||
import { PluginIndexComponent } from '../plugin-index/plugin-index.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Log } from '../../../core/log';
|
||||
import { PluginLog } from '../../../core/log';
|
||||
|
||||
/**
|
||||
* Container component for rendering plugin iframes in the right panel.
|
||||
|
|
@ -57,7 +57,7 @@ export class PluginPanelContainerComponent implements OnInit, OnDestroy {
|
|||
.select(selectActivePluginId)
|
||||
.pipe(filter((pluginId): pluginId is string => !!pluginId))
|
||||
.subscribe((pluginId) => {
|
||||
Log.log('Plugin panel container received active plugin ID:', pluginId);
|
||||
PluginLog.log('Plugin panel container received active plugin ID:', pluginId);
|
||||
this.activePluginId.set(pluginId);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { Log } from '../../core/log';
|
||||
import { PluginLog } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Component that renders side panel buttons for plugins in the main header.
|
||||
|
|
@ -133,21 +133,21 @@ export class PluginSidePanelBtnsComponent {
|
|||
});
|
||||
|
||||
onButtonClick(button: PluginSidePanelBtnCfg): void {
|
||||
Log.log('Side panel button clicked:', button.pluginId, button.label);
|
||||
PluginLog.log('Side panel button clicked:', button.pluginId, button.label);
|
||||
|
||||
// Prevent action if not in work view
|
||||
if (!this.isWorkView()) {
|
||||
Log.log('Not in work view, ignoring click');
|
||||
PluginLog.log('Not in work view, ignoring click');
|
||||
return;
|
||||
}
|
||||
|
||||
Log.log('Dispatching togglePluginPanel action for:', button.pluginId);
|
||||
PluginLog.log('Dispatching togglePluginPanel action for:', button.pluginId);
|
||||
// Dispatch action to toggle the plugin panel
|
||||
this._store.dispatch(togglePluginPanel(button.pluginId));
|
||||
|
||||
// Call the original onClick handler if provided
|
||||
if (button.onClick) {
|
||||
Log.log('Calling plugin onClick handler for:', button.pluginId);
|
||||
PluginLog.log('Calling plugin onClick handler for:', button.pluginId);
|
||||
button.onClick();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { PluginBridgeService } from '../plugin-bridge.service';
|
||||
import { PluginBaseCfg, PluginManifest } from '../plugin-api.model';
|
||||
import { Log } from '../../core/log';
|
||||
import { PluginLog } from '../../core/log';
|
||||
|
||||
/**
|
||||
* Simplified plugin iframe utilities following KISS principles.
|
||||
|
|
@ -150,7 +150,7 @@ export const createPluginApiScript = (config: PluginIframeConfig): string => {
|
|||
try {
|
||||
handler(data.payload);
|
||||
} catch (error) {
|
||||
Log.err('Hook handler error:', error);
|
||||
PluginLog.err('Hook handler error:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -372,7 +372,7 @@ export const handlePluginMessage = async (
|
|||
// Special handling for registerHook - it needs pluginId as first parameter
|
||||
if (args.length >= 2) {
|
||||
const [hook, handlerPlaceholder] = args;
|
||||
Log.log('Plugin iframe registerHook:', {
|
||||
PluginLog.log('Plugin iframe registerHook:', {
|
||||
hook,
|
||||
handlerPlaceholder,
|
||||
pluginId: config.pluginId,
|
||||
|
|
@ -524,6 +524,6 @@ export const handlePluginMessage = async (
|
|||
|
||||
// Handle plugin ready
|
||||
if (data.type === 'plugin-ready' && data.pluginId === config.pluginId) {
|
||||
Log.log(`Plugin ${config.pluginId} is ready`);
|
||||
PluginLog.log(`Plugin ${config.pluginId} is ready`);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue