-
-
Notifications
You must be signed in to change notification settings - Fork 6
Simplify DOM watcher with configuration-level settings and automatic action restart #668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 22 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
cb64521
Initial plan
Copilot fb5c90a
Add core DOM watcher infrastructure with action integration
Copilot 33eb9cf
Add DevTools integration and messaging for DOM watcher
Copilot 96e1b61
Complete DOM watcher implementation with UI and documentation
Copilot dfeaf47
Add sequential action restart modes for DOM watcher
Copilot 849340b
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram eb75504
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram 5307c51
fix: add lang attribute to html tag for accessibility
dharmesh-hemaram 366a243
Update apps/acf-options-page/src/store/config/action/settings/action-…
dharmesh-hemaram 08416a7
Update apps/acf-options-page/src/store/config/action/settings/action-…
dharmesh-hemaram 89d4a6d
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram 2234b28
Update i18next to version 25.4.2 and remove isbot dependency from pac…
dharmesh-hemaram ac1dc21
still working
dharmesh-hemaram 7ad38ab
feat: Add Watch Settings Modal and integrate with action configuration
dharmesh-hemaram 20170c0
Merge branch 'main' into copilot/fix-667
dharmesh-hemaram f2f86f0
Move DOM watcher from action-level to configuration-level settings
Copilot 6f236a3
refactor: Remove DOM watcher from action and batch processing, integr…
dharmesh-hemaram 5638e1d
Fixed lint error
dharmesh-hemaram b386572
refactor: remove DOM watcher implementation and related DevTools inte…
dharmesh-hemaram 6258183
fix: correct filtering logic in filterProcessedElements function
dharmesh-hemaram 83e968b
fix: ensure elements are processed after filtering in start function
dharmesh-hemaram 91fc60b
Refactor code structure for improved readability and maintainability
dharmesh-hemaram d09ab17
Fixed lint error
dharmesh-hemaram e085b30
fix: update UUID generation in config-watch tests and remove outdated…
dharmesh-hemaram 34111f8
fix: add missing dependency for @firebase/util in package.json
dharmesh-hemaram 23edcb8
fix: update SWC dependencies and remove unused @firebase/util dependency
dharmesh-hemaram d16cbcd
Implement feature X to enhance user experience and fix bug Y in module Z
dharmesh-hemaram ccc3b1c
Update packages/acf/common/src/lib/model/IWatch.ts
dharmesh-hemaram 4a5f6a4
Update site/src/content/html/textarea.html
dharmesh-hemaram 754885f
Update apps/acf-extension/src/content_scripts/util/dom-watch-manager.ts
dharmesh-hemaram 5a249b7
Update apps/acf-options-page/src/modal/config-watch/watch-settings.tsx
dharmesh-hemaram bf30a8a
Fixed lint error
dharmesh-hemaram 294ce4f
Remove Verdaccio config and update package-lock.json and package.json…
dharmesh-hemaram File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
apps/acf-extension/src/content_scripts/util/dom-watch-manager.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import { IWatchSettings, defaultWatchSettings } from '@dhruv-techapps/acf-common'; | ||
|
||
interface DomWatchState { | ||
isActive: boolean; | ||
observer: MutationObserver | null; | ||
watchSettings: IWatchSettings | null; | ||
debounceTimeout: number | null; | ||
currentUrl: string; | ||
startTime: number; | ||
sequenceRestartCallback?: () => Promise<void>; | ||
} | ||
|
||
const DomWatchManager = (() => { | ||
const state: DomWatchState = { | ||
isActive: false, | ||
observer: null, | ||
watchSettings: null, | ||
debounceTimeout: null, | ||
currentUrl: window.location.href, | ||
startTime: 0, | ||
sequenceRestartCallback: undefined | ||
}; | ||
|
||
// Process added nodes and check if any match actions | ||
const processAddedNodes = async (addedNodes: NodeList): Promise<void> => { | ||
if (!state.watchSettings || !state.sequenceRestartCallback) { | ||
return; | ||
} | ||
|
||
console.debug('DomWatchManager: Restarting action sequence due to DOM changes'); | ||
await state.sequenceRestartCallback(); | ||
}; | ||
|
||
// Debounced processing | ||
const debounceProcessing = (processingFn: () => Promise<void>, delay: number): void => { | ||
// Clear existing timeout | ||
if (state.debounceTimeout) { | ||
clearTimeout(state.debounceTimeout); | ||
} | ||
|
||
// Set new timeout | ||
state.debounceTimeout = window.setTimeout(async () => { | ||
try { | ||
await processingFn(); | ||
} catch (error) { | ||
console.error('DomWatchManager: Error in debounced processing:', error); | ||
} | ||
state.debounceTimeout = null; | ||
}, delay); | ||
}; | ||
|
||
// Check lifecycle stop conditions | ||
const shouldStopWatching = (): boolean => { | ||
if (!state.watchSettings?.lifecycleStopConditions) return false; | ||
|
||
const { lifecycleStopConditions } = state.watchSettings; | ||
|
||
// Check timeout | ||
if (lifecycleStopConditions.timeout) { | ||
const elapsed = Date.now() - state.startTime; | ||
if (elapsed >= lifecycleStopConditions.timeout * 60 * 1000) { | ||
// Convert mins to milliseconds | ||
console.debug('DomWatchManager: Stopping due to timeout'); | ||
return true; | ||
} | ||
} | ||
|
||
// Check URL change | ||
if (lifecycleStopConditions.urlChange && state.currentUrl !== window.location.href) { | ||
console.debug('DomWatchManager: Stopping due to URL change'); | ||
return true; | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
// Mutation observer callback | ||
const handleMutations = (mutations: MutationRecord[]): void => { | ||
if (!state.isActive || !state.watchSettings) { | ||
return; | ||
} | ||
|
||
// Check if we should stop watching | ||
if (shouldStopWatching()) { | ||
return; | ||
} | ||
|
||
for (const mutation of mutations) { | ||
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { | ||
// Debounce the processing to avoid excessive restarts | ||
debounceProcessing( | ||
() => processAddedNodes(mutation.addedNodes), | ||
(state.watchSettings.debounce || 1) * 1000 // Convert seconds to milliseconds | ||
); | ||
} | ||
} | ||
}; | ||
|
||
// Initialize the mutation observer | ||
const initializeObserver = (): void => { | ||
if (state.observer || !state.watchSettings) { | ||
return; | ||
} | ||
|
||
const watchRoot = state.watchSettings.watchRootSelector || 'body'; | ||
const rootElements = document.querySelectorAll<HTMLElement>(watchRoot) || document.body; | ||
dharmesh-hemaram marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
state.observer = new MutationObserver(handleMutations); | ||
rootElements.forEach((rootElement) => { | ||
state.observer?.observe(rootElement, { | ||
childList: true, | ||
subtree: true, | ||
attributes: !!state.watchSettings?.watchAttributes, // track attributes | ||
attributeFilter: state.watchSettings?.watchAttributes // optional optimization | ||
}); | ||
}); | ||
|
||
console.debug(`DomWatchManager: Initialized observer on ${watchRoot}`); | ||
}; | ||
|
||
// Register configuration-level DOM watching | ||
const registerConfiguration = (watchSettings: IWatchSettings): void => { | ||
if (!watchSettings.watchEnabled) { | ||
return; | ||
} | ||
|
||
const mergedSettings: IWatchSettings = { | ||
...defaultWatchSettings, | ||
...watchSettings | ||
}; | ||
|
||
state.watchSettings = mergedSettings; | ||
state.startTime = Date.now(); | ||
if (!state.isActive) { | ||
start(); | ||
} | ||
|
||
console.debug(`DomWatchManager: Registered configuration-level DOM watching`); | ||
}; | ||
|
||
// Start DOM watching | ||
const start = (): void => { | ||
if (state.isActive || !state.watchSettings) { | ||
return; | ||
} | ||
|
||
state.isActive = true; | ||
state.currentUrl = window.location.href; | ||
initializeObserver(); | ||
|
||
console.debug('DomWatchManager: Started configuration-level DOM watching'); | ||
}; | ||
|
||
// Get current watch status | ||
const getStatus = () => ({ | ||
isActive: state.isActive, | ||
watchEnabled: state.watchSettings?.watchEnabled || false, | ||
startTime: state.startTime, | ||
settings: state.watchSettings | ||
}); | ||
|
||
// Set the callback function for sequence restart | ||
const setSequenceRestartCallback = (callback: () => Promise<void>): void => { | ||
state.sequenceRestartCallback = callback; | ||
}; | ||
|
||
return { | ||
registerConfiguration, | ||
setSequenceRestartCallback, | ||
start, | ||
getStatus | ||
}; | ||
})(); | ||
|
||
export default DomWatchManager; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"fileNames":[],"fileInfos":[],"root":[],"options":{"composite":true,"declarationMap":true,"emitDeclarationOnly":true,"importHelpers":true,"module":99,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noUnusedLocals":true,"skipLibCheck":true,"strict":true,"target":9},"version":"5.9.2"} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,7 @@ | |
{ | ||
"projects": ["acf-extension"], | ||
"target": "serve" | ||
}, | ||
"watch-deps" | ||
} | ||
] | ||
} | ||
} | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.