Skip to content

Commit

Permalink
Added devtools
Browse files Browse the repository at this point in the history
  • Loading branch information
dharmesh-hemaram committed Sep 9, 2024
1 parent 3e70ad1 commit ea52854
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 178 deletions.
8 changes: 4 additions & 4 deletions apps/acf-extension/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
{
"entryName": "wizard-popup",
"entryPath": "apps/acf-extension/src/wizard/popup/wizard-popup.ts"
},
{
"entryName": "devtools",
"entryPath": "apps/acf-extension/src/devtools/index.ts"
}
],
"styles": ["apps/acf-extension/src/wizard/popup/wizard-popup.scss", "libs/shared/status-bar/src/lib/status-bar.scss"],
Expand Down Expand Up @@ -86,10 +90,6 @@
{
"entryName": "devtools",
"entryPath": "apps/acf-extension/src/devtools/index.ts"
},
{
"entryName": "recorder",
"entryPath": "apps/acf-extension/src/devtools/recorder/index.ts"
}
],
"styles": ["apps/acf-extension/src/wizard/popup/wizard-popup.scss", "libs/shared/status-bar/src/lib/status-bar.scss"],
Expand Down
7 changes: 7 additions & 0 deletions apps/acf-extension/src/devtools/chrome-devtools.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare namespace chrome {
namespace devtools {
namespace recorder {
function registerRecorderExtensionPlugin(plugin: any, name: string, mediaType: string): void;
}
}
}
97 changes: 97 additions & 0 deletions apps/acf-extension/src/devtools/converter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Action, CONFIG_SOURCE, Configuration, getDefaultAction, getDefaultConfig } from '@dhruv-techapps/acf-common';

import { Recording, Step } from './index.types';

const getProps = (selectors: Array<Array<string>>) => {
let elementFinder = '';
let name = '';
selectors.flat().every((selector) => {
if (selector.startsWith('xpath/')) {
elementFinder = selector.replace('xpath/', '');
return false;
} else if (selector.startsWith('text/')) {
elementFinder = `//*[contains(text(),"${selector.replace('text/', '')}")`;
return false;
} else if (selector.startsWith('aria/')) {
name = selector.replace('aria/', '');
}
return true;
});
return { elementFinder, name };
};

export const ConvertStep = (step: Step) => {
const action: Action = getDefaultAction();
switch (step.type) {
case 'change':
{
console.assert(step.selectors, 'Selectors are required for change step');
console.assert(step.value, 'Value is required for change step');
const { elementFinder, name } = getProps(step.selectors);
action.elementFinder = elementFinder;
action.name = name;
action.selectors = step.selectors;
action.value = step.value;
}
break; // Add an expression here if needed
case 'click':
case 'doubleClick':
{
console.assert(step.selectors, 'Selectors are required for click step');
const { elementFinder, name } = getProps(step.selectors);
action.elementFinder = elementFinder;
action.name = name;
action.selectors = step.selectors;
}

break;
case 'keyDown':
case 'keyUp':
case 'navigate':
case 'setViewport':
break;
default:
console.assert(false, `Unknown step type: ${step}`);
}
if (step.timeout) {
action.settings = { retry: step.timeout / 1000, retryInterval: 1 };
}
delete action.error;
return action;
};

const getConfig = (url: string) => {
const config: Configuration = getDefaultConfig(CONFIG_SOURCE.RECORDER);
config.actions = [];
config.url = url;
delete config.updated;
return config;
};

export const ConvertRecording = (recording: Recording) => {
const configs: Array<Configuration> = [];
const [, navigate, ...steps] = recording.steps;
let config: Configuration;
if (navigate.type === 'navigate') {
console.assert(navigate.url, 'URL is required for navigate step');
config = getConfig(navigate.url);
configs.push(config);
}

console.assert(steps.length === 0, 'No steps found in recording');
steps.forEach((step) => {
const action = ConvertStep(step);
if (action && action.elementFinder) {
config.actions.push(action);
}
if (step.assertedEvents) {
step.assertedEvents.forEach((assertedEvent) => {
if (assertedEvent.type === 'navigation' && assertedEvent.url !== config.url) {
configs.push(config);
config = getConfig(assertedEvent.url);
}
});
}
});
return configs;
};
107 changes: 1 addition & 106 deletions apps/acf-extension/src/devtools/devtools.html
Original file line number Diff line number Diff line change
@@ -1,106 +1 @@
<html>
<body>
<script src="devtools.js"></script>
<div id="body" class="modal position-static d-block" data-bs-theme="light">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h6 class="modal-title text-truncate">Auto Clicker - AutoFill</h6>
<div class="d-flex justify-content-center align-items-center">
<button type="button" class="btn ms-2" aria-label="collapse">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrows-expand" style="display: none" viewBox="0 0 16 16">
<path
fill-rule="evenodd"
d="M1 8a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 0 1h-13A.5.5 0 0 1 1 8ZM7.646.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 1.707V5.5a.5.5 0 0 1-1 0V1.707L6.354 2.854a.5.5 0 1 1-.708-.708l2-2ZM8 10a.5.5 0 0 1 .5.5v3.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L7.5 14.293V10.5A.5.5 0 0 1 8 10Z"
/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-lg" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2 8a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11A.5.5 0 0 1 2 8Z" />
</svg>
</button>
<button type="button" class="btn ms-2" data-bs-dismiss="modal" aria-label="Close">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
<path
d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"
/>
</svg>
</button>
</div>
</header>
<main class="modal-body" id="collapse-main">
<slot name="actions" hidden>
<table class="table table-sm table-hover mb-0">
<thead>
<tr>
<th scope="col">Name/Element</th>
<th scope="col">Value</th>
<th scope="col"></th>
</tr>
</thead>
<tbody class="table-group-divider"></tbody>
</table>
</slot>
<slot name="no-actions">
<div class="px-2">
<div class="card w-100">
<div class="card-body">
<h5 class="card-title mb-3 text-primary">Start filling form...</h5>
<hr />
<h6 class="card-subtitle mb-2 text-muted">If you have already filled form</h6>
<button type="button" auto-generate-config class="btn btn-sm btn-outline-secondary">Already Filled ?</button>
</div>
</div>
</div>
</slot>
</main>
<footer class="modal-footer justify-content-center" id="collapse-footer">
<ul class="nav justify-content-between w-100">
<li class="nav-item">
<a href="https://getautoclicker.com/docs/4.x/getting-started" class="nav-link px-2 text-muted" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-richtext" viewBox="0 0 16 16">
<path
d="M7 4.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0zm-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047l1.888.974V7.5a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V7s1.54-1.274 1.639-1.208zM5 9a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm0 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1H5z"
/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z" />
</svg>
<span id="docs-text"></span>
</a>
</li>
<li class="nav-item">
<a href="https://discord.gg/ubMBeX3" class="nav-link px-2 text-muted" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-fill" viewBox="0 0 16 16">
<path
d="M8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6-.097 1.016-.417 2.13-.771 2.966-.079.186.074.394.273.362 2.256-.37 3.597-.938 4.18-1.234A9.06 9.06 0 0 0 8 15z"
/>
</svg>
<span id="chat-text"></span>
</a>
</li>
<li class="nav-item">
<a href="https://dev.getautoclicker.com/" class="nav-link px-2 text-muted" target="_blank" id="settings">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear-fill" viewBox="0 0 16 16">
<path
d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"
/>
</svg>
<span id="advance-text"></span>
</a>
</li>
<li class="nav-item">
<a href="https://github.com/sponsors/Dhruv-Techapps" class="nav-link px-2 text-muted" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-balloon-heart text-danger" viewBox="0 0 16 16">
<path
fill-rule="evenodd"
d="m8 2.42-.717-.737c-1.13-1.161-3.243-.777-4.01.72-.35.685-.451 1.707.236 3.062C4.16 6.753 5.52 8.32 8 10.042c2.479-1.723 3.839-3.29 4.491-4.577.687-1.355.587-2.377.236-3.061-.767-1.498-2.88-1.882-4.01-.721L8 2.42Zm-.49 8.5c-10.78-7.44-3-13.155.359-10.063.045.041.089.084.132.129.043-.045.087-.088.132-.129 3.36-3.092 11.137 2.624.357 10.063l.235.468a.25.25 0 1 1-.448.224l-.008-.017c.008.11.02.202.037.29.054.27.161.488.419 1.003.288.578.235 1.15.076 1.629-.157.469-.422.867-.588 1.115l-.004.007a.25.25 0 1 1-.416-.278c.168-.252.4-.6.533-1.003.133-.396.163-.824-.049-1.246l-.013-.028c-.24-.48-.38-.758-.448-1.102a3.177 3.177 0 0 1-.052-.45l-.04.08a.25.25 0 1 1-.447-.224l.235-.468ZM6.013 2.06c-.649-.18-1.483.083-1.85.798-.131.258-.245.689-.08 1.335.063.244.414.198.487-.043.21-.697.627-1.447 1.359-1.692.217-.073.304-.337.084-.398Z"
/>
</svg>
<span id="sponsor-text"></span>
</a>
</li>
</ul>
</footer>
</div>
</div>
</div>
</body>
</html>
<script type="module" src="./devtools.js"></script>
17 changes: 14 additions & 3 deletions apps/acf-extension/src/devtools/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
chrome.devtools.panels.create('demo panel', 'icon.png', 'recorder.html', () => {
console.log('user switched to this panel');
});
import { ConvertRecording, ConvertStep } from './converter';
import { Recording, Step } from './index.types';

export class RecorderPlugin {
stringify(recording: Recording) {
return Promise.resolve(JSON.stringify(ConvertRecording(recording)));
}
stringifyStep(step: Step) {
return Promise.resolve(JSON.stringify(ConvertStep(step)));
}
}

/* eslint-disable no-undef */
chrome.devtools.recorder.registerRecorderExtensionPlugin(new RecorderPlugin(), 'Auto Clicker Auto Fill', 'application/json');
46 changes: 46 additions & 0 deletions apps/acf-extension/src/devtools/index.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
type NavigationStep = {
type: 'navigate';
url: string;
};

type SetViewportStep = {
type: 'setViewport';
width: number;
height: number;
deviceScaleFactor: number;
isMobile: boolean;
hasTouch: boolean;
isLandscape: boolean;
};
type ChangeStep = {
target: string;
type: 'change';
selectors: Array<Array<string>>;
value: string;
};

type ClickStep = {
target: string;
type: 'click' | 'doubleClick';
selectors: Array<Array<string>>;
offsetY: number;
offsetX: number;
};

type KeyStep = {
target: string;
type: 'keyDown' | 'keyUp';
key: string;
};

type AssertedEvents = {
type: string;
url: string;
title: string;
};

export type Step = (NavigationStep | SetViewportStep | ChangeStep | ClickStep | KeyStep) & { assertedEvents?: Array<AssertedEvents>; timeout: number };
export type Recording = {
title: string;
steps: Array<Step>;
};
14 changes: 0 additions & 14 deletions apps/acf-extension/src/devtools/recorder/index.ts

This file was deleted.

48 changes: 0 additions & 48 deletions apps/acf-extension/src/devtools/recorder/recorder.html

This file was deleted.

1 change: 0 additions & 1 deletion apps/acf-extension/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ module.exports = composePlugins(withNx(), (config, ctx) => {
{ from: path.join(__dirname, 'assets', config.watch ? 'DEV' : process.env.NX_PUBLIC_VARIANT), to: './assets' },
{ from: `./*.html`, to: './html', context: 'src/wizard/popup' },
{ from: `./*.html`, to: './', context: 'src/devtools' },
{ from: `./*.html`, to: './', context: 'src/devtools/recorder' },
{ from: `./*.html`, to: './html', context: '../../libs/shared/sandbox/src/lib' },
{ from: path.join(ctx.options.root, './node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js'), to: './webcomponents' },
{
Expand Down
2 changes: 1 addition & 1 deletion apps/acf-options-page/src/store/config/config.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const slice = createSlice({
state.selectedConfigId = state.configs[0].id;
},
importAll: (state, action: PayloadAction<Array<Configuration>>) => {
state.configs = { ...state.configs, ...updateConfigIds(action.payload) };
state.configs.push(...updateConfigIds(action.payload));
state.selectedConfigId = state.configs[0].id;
},
importConfig: (state, action: PayloadAction<Configuration>) => {
Expand Down
1 change: 1 addition & 0 deletions libs/acf/common/src/lib/model/action-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export type Action = {
status?: string;
error?: string[];
valueFieldType?: 'text' | 'textarea';
selectors?: Array<Array<string>>;
};

export const getDefaultAction = (): Action => ({
Expand Down
Loading

0 comments on commit ea52854

Please sign in to comment.