Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cb64521
Initial plan
Copilot Aug 22, 2025
fb5c90a
Add core DOM watcher infrastructure with action integration
Copilot Aug 22, 2025
33eb9cf
Add DevTools integration and messaging for DOM watcher
Copilot Aug 22, 2025
96e1b61
Complete DOM watcher implementation with UI and documentation
Copilot Aug 22, 2025
dfeaf47
Add sequential action restart modes for DOM watcher
Copilot Aug 27, 2025
849340b
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram Aug 27, 2025
eb75504
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram Aug 27, 2025
5307c51
fix: add lang attribute to html tag for accessibility
dharmesh-hemaram Aug 27, 2025
366a243
Update apps/acf-options-page/src/store/config/action/settings/action-…
dharmesh-hemaram Aug 28, 2025
08416a7
Update apps/acf-options-page/src/store/config/action/settings/action-…
dharmesh-hemaram Aug 28, 2025
89d4a6d
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram Aug 28, 2025
2234b28
Update i18next to version 25.4.2 and remove isbot dependency from pac…
dharmesh-hemaram Aug 28, 2025
ac1dc21
still working
dharmesh-hemaram Aug 28, 2025
7ad38ab
feat: Add Watch Settings Modal and integrate with action configuration
dharmesh-hemaram Aug 28, 2025
20170c0
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram Aug 28, 2025
f2f86f0
Move DOM watcher from action-level to configuration-level settings
Copilot Aug 28, 2025
6f236a3
refactor: Remove DOM watcher from action and batch processing, integr…
dharmesh-hemaram Aug 28, 2025
5638e1d
Fixed lint error
dharmesh-hemaram Aug 28, 2025
b386572
refactor: remove DOM watcher implementation and related DevTools inte…
dharmesh-hemaram Aug 29, 2025
6258183
fix: correct filtering logic in filterProcessedElements function
dharmesh-hemaram Aug 29, 2025
83e968b
fix: ensure elements are processed after filtering in start function
dharmesh-hemaram Aug 29, 2025
91fc60b
Refactor code structure for improved readability and maintainability
dharmesh-hemaram Aug 29, 2025
d09ab17
Fixed lint error
dharmesh-hemaram Aug 29, 2025
e085b30
fix: update UUID generation in config-watch tests and remove outdated…
dharmesh-hemaram Aug 29, 2025
34111f8
fix: add missing dependency for @firebase/util in package.json
dharmesh-hemaram Aug 29, 2025
23edcb8
fix: update SWC dependencies and remove unused @firebase/util dependency
dharmesh-hemaram Aug 29, 2025
d16cbcd
Implement feature X to enhance user experience and fix bug Y in module Z
dharmesh-hemaram Aug 29, 2025
ccc3b1c
Update packages/acf/common/src/lib/model/IWatch.ts
dharmesh-hemaram Aug 29, 2025
4a5f6a4
Update site/src/content/html/textarea.html
dharmesh-hemaram Aug 29, 2025
754885f
Update apps/acf-extension/src/content_scripts/util/dom-watch-manager.ts
dharmesh-hemaram Aug 29, 2025
5a249b7
Update apps/acf-options-page/src/modal/config-watch/watch-settings.tsx
dharmesh-hemaram Aug 29, 2025
bf30a8a
Fixed lint error
dharmesh-hemaram Aug 29, 2025
294ce4f
Remove Verdaccio config and update package-lock.json and package.json…
dharmesh-hemaram Aug 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions apps/acf-extension/src/background/dom-watcher-devtools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { RUNTIME_MESSAGE_ACF } from '@dhruv-techapps/acf-common';

Check warning on line 1 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L1

ES2015 modules are forbidden.

// DevTools communication handler for DOM Watcher
export class DomWatcherDevToolsBackground {
private devToolsPorts: Map<number, chrome.runtime.Port> = new Map();

Check warning on line 5 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L5

ES2022 field 'devToolsPorts' is forbidden.

constructor() {
// Listen for DevTools connections
chrome.runtime.onConnect.addListener((port) => {
if (port.name === 'dom-watcher-devtools') {
this.handleDevToolsConnection(port);
}
});
}

private handleDevToolsConnection(port: chrome.runtime.Port) {
const tabId = port.sender?.tab?.id;
if (!tabId) {
console.error('DomWatcherDevTools: No tab ID in port connection');
return;
}

console.log(`DomWatcherDevTools: Connected to tab ${tabId}`);
this.devToolsPorts.set(tabId, port);

// Handle messages from DevTools
port.onMessage.addListener((message) => {

Check warning on line 27 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L27

ES2015 arrow function expressions are forbidden.
this.handleDevToolsMessage(message, tabId);
});

// Clean up on disconnect
port.onDisconnect.addListener(() => {

Check warning on line 32 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L32

Unsafe call of an `error` type typed value.
console.log(`DomWatcherDevTools: Disconnected from tab ${tabId}`);
this.devToolsPorts.delete(tabId);

Check warning on line 34 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L34

Unsafe argument of type `any` assigned to a parameter of type `number`.
});
}

private async handleDevToolsMessage(message: any, tabId: number) {

Check warning on line 38 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L38

ES2017 async function declarations are forbidden.

Check warning on line 38 in apps/acf-extension/src/background/dom-watcher-devtools.ts

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

apps/acf-extension/src/background/dom-watcher-devtools.ts#L38

Missing return type on function.
try {
switch (message.type) {
case 'GET_WATCHER_STATUS':
await this.getWatcherStatus(tabId);
break;
case 'WATCHER_COMMAND':
await this.sendWatcherCommand(tabId, message.command);
break;
default:
console.warn('DomWatcherDevTools: Unknown message type:', message.type);
}
} catch (error) {
console.error('DomWatcherDevTools: Error handling message:', error);
}
}

private async getWatcherStatus(tabId: number) {
try {
// Send message to content script to get watcher status
const response = await chrome.tabs.sendMessage(tabId, {
action: RUNTIME_MESSAGE_ACF.DOM_WATCHER_GET_STATUS
});

// Forward response to DevTools
const port = this.devToolsPorts.get(tabId);
if (port) {
port.postMessage({
type: 'WATCHER_STATUS',
data: response || { isActive: false, watchedActionsCount: 0, watchedActions: [] }
});
}
} catch (error) {
console.error('DomWatcherDevTools: Error getting watcher status:', error);

// Send default status on error
const port = this.devToolsPorts.get(tabId);
if (port) {
port.postMessage({
type: 'WATCHER_STATUS',
data: { isActive: false, watchedActionsCount: 0, watchedActions: [] }
});
}
}
}

private async sendWatcherCommand(tabId: number, command: string) {
try {
await chrome.tabs.sendMessage(tabId, {
action: RUNTIME_MESSAGE_ACF.DOM_WATCHER_COMMAND,
command
});

// Get updated status after command
setTimeout(() => this.getWatcherStatus(tabId), 100);
} catch (error) {
console.error('DomWatcherDevTools: Error sending watcher command:', error);
}
}

// Send log messages to DevTools
public sendLogToDevTools(tabId: number, message: string, level: 'debug' | 'info' | 'warning' | 'error' = 'debug') {
const port = this.devToolsPorts.get(tabId);
if (port) {
port.postMessage({
type: 'WATCHER_LOG',
data: { message, level }
});
}
}
}
6 changes: 6 additions & 0 deletions apps/acf-extension/src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { scope } from '../common/instrument';
import AcfBackup from './acf-backup';
import { AcfSchedule } from './acf-schedule';
import registerContextMenus from './context-menu';
import { DomWatcherDevToolsBackground } from './dom-watcher-devtools';
import { auth } from './firebase';
import { googleAnalytics } from './google-analytics';
import { TabsMessenger } from './tab';
Expand Down Expand Up @@ -104,6 +105,11 @@ try {
*/
registerNotifications(OPTIONS_PAGE_URL);

/**
* Initialize DOM Watcher DevTools communication
*/
new DomWatcherDevToolsBackground();

/**
* Setup on Message Listener
*/
Expand Down
14 changes: 13 additions & 1 deletion apps/acf-extension/src/content_scripts/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { I18N_COMMON, I18N_ERROR } from './i18n';
import Statement from './statement';
import { statusBar } from './status-bar';
import UserScriptProcessor from './userscript';
import DomWatchManager from './util/dom-watch-manager';

const ACTION_I18N = {
TITLE: chrome.i18n.getMessage('@ACTION__TITLE'),
Expand All @@ -36,6 +37,10 @@ const Actions = (() => {

const start = async (actions: Array<IAction | IUserScript>, batchRepeat: number) => {
window.ext.__batchRepeat = batchRepeat;

// Clear any existing DOM watchers before starting new actions
DomWatchManager.clear();

let i = 0;
while (i < actions.length) {
const action = actions[i];
Expand All @@ -55,6 +60,13 @@ const Actions = (() => {
action.status = await UserScriptProcessor.start(action as IUserScript);
} else {
action.status = await ActionProcessor.start(action as IAction);

// Register action for DOM watching if enabled (only for regular actions, not userscripts)
const typedAction = action as IAction;
if (typedAction.settings?.watch?.watchEnabled) {
console.debug(`${ACTION_I18N.TITLE} #${i + 1}`, `[${window.ext.__currentActionName}]`, '👁️ Registering for DOM watching');
DomWatchManager.registerAction(typedAction);
}
}
notify(action);
} catch (error) {
Expand All @@ -76,7 +88,7 @@ const Actions = (() => {
i += 1;
}
};
return { start };
return { start, getDomWatchManager: () => DomWatchManager };
})();

export default Actions;
48 changes: 46 additions & 2 deletions apps/acf-extension/src/content_scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ELoadTypes, RUNTIME_MESSAGE_ACF } from '@dhruv-techapps/acf-common';
import { ConfigStorage, GetConfigResult, SettingsStorage } from '@dhruv-techapps/acf-store';
import { IExtension, Logger, LoggerColor } from '@dhruv-techapps/core-common';
import { scope } from '../common/instrument';
import Actions from './actions';
import ConfigProcessor from './config';
import { statusBar } from './status-bar';

Expand Down Expand Up @@ -64,8 +65,9 @@ self.onerror = (...rest) => {
scope.captureException({ ...rest }, { captureContext: { tags: { errorType: 'onerror' } } });
};

chrome.runtime.onMessage.addListener(async (message) => {
const { action, configId } = message;
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
const { action, configId, command } = message;

if (action === RUNTIME_MESSAGE_ACF.RUN_CONFIG) {
try {
new ConfigStorage().getConfigById(configId).then(async (config) => {
Expand All @@ -88,5 +90,47 @@ chrome.runtime.onMessage.addListener(async (message) => {
}
scope.captureException(e);
}
} else if (action === RUNTIME_MESSAGE_ACF.DOM_WATCHER_GET_STATUS) {
// Handle DOM watcher status request
try {
const domWatchManager = Actions.getDomWatchManager();
const status = domWatchManager.getStatus();
sendResponse(status);
} catch (e) {
console.error('Error getting DOM watcher status:', e);
sendResponse({ isActive: false, watchedActionsCount: 0, watchedActions: [] });
}
return true; // Keep message channel open for async response
} else if (action === RUNTIME_MESSAGE_ACF.DOM_WATCHER_COMMAND) {
// Handle DOM watcher commands
try {
const domWatchManager = Actions.getDomWatchManager();

switch (command) {
case 'START':
domWatchManager.start();
break;
case 'STOP':
domWatchManager.stop();
break;
case 'PAUSE':
domWatchManager.pause();
break;
case 'RESUME':
domWatchManager.resume();
break;
case 'CLEAR':
domWatchManager.clear();
break;
default:
console.warn('Unknown DOM watcher command:', command);
}

sendResponse({ success: true });
} catch (e) {
console.error('Error handling DOM watcher command:', e);
sendResponse({ success: false, error: e.message });
}
return true; // Keep message channel open for async response
}
});
Loading