Browse Source

fix: record workflow

Ahmad Kholid 3 years ago
parent
commit
531bccbdab

+ 8 - 4
src/background/index.js

@@ -182,6 +182,8 @@ browser.webNavigation.onCommitted.addListener(
     if (frameId !== 0 || !allowedType.includes(transitionType)) return;
 
     updateRecording((recording) => {
+      if (tabId !== recording.activeTab.id) return;
+
       const lastFlow = recording.flows[recording.flows.length - 1];
       const isClickSubmit =
         lastFlow.id === 'event-click' && transitionType === 'form_submit';
@@ -215,7 +217,7 @@ browser.webNavigation.onCommitted.addListener(
   }
 );
 browser.tabs.onActivated.addListener(async ({ tabId }) => {
-  const { url, id } = await browser.tabs.get(tabId);
+  const { url, id, title } = await browser.tabs.get(tabId);
 
   if (!validateUrl(url)) return;
 
@@ -223,11 +225,11 @@ browser.tabs.onActivated.addListener(async ({ tabId }) => {
     recording.activeTab = { id, url };
     recording.flows.push({
       id: 'switch-tab',
-      description: url,
       data: {
         url,
         matchPattern: url,
         createIfNoMatch: true,
+        description: title || url,
       },
     });
   });
@@ -250,8 +252,10 @@ browser.tabs.onCreated.addListener(async (tab) => {
 
     recording.flows.push({
       id: 'new-tab',
-      description: validUrl,
-      data: { url: validUrl },
+      data: {
+        url: validUrl,
+        description: tab.title || validUrl,
+      },
     });
   }
 

+ 18 - 8
src/content/services/record-workflow.js

@@ -29,38 +29,42 @@ function changeListener({ target }) {
   let block = null;
   const selector = finder(target);
   const isSelectEl = target.tagName === 'SELECT';
-  const elementName = target.ariaLabel || target.name || selector;
+  const elementName = target.ariaLabel || target.name;
 
   if (isInputEl && inputType === 'file') {
     block = {
       id: 'upload-file',
-      description: elementName,
+      description: elementName || selector,
       data: {
         selector,
+        waitForSelector: true,
+        description: elementName,
         filePaths: [target.value],
       },
     };
   } else if (textFieldEl(target) || isSelectEl) {
     block = {
       id: 'forms',
-      description: `${isSelectEl ? 'Select' : 'Text field'} (${elementName})`,
       data: {
         selector,
         delay: 100,
         clearValue: true,
         value: target.value,
+        waitForSelector: true,
         type: isSelectEl ? 'select' : 'text-field',
+        description: `${isSelectEl ? 'Select' : 'Text field'} (${elementName})`,
       },
     };
   } else {
     block = {
       id: 'trigger-event',
-      description: `Change event (${selector})`,
       data: {
         selector,
         eventName: 'change',
         eventType: 'event',
+        waitForSelector: true,
         eventParams: { bubbles: true },
+        description: `Change event (${selector})`,
       },
     };
   }
@@ -94,7 +98,6 @@ function keyEventListener({
 
   addBlock({
     id: 'trigger-event',
-    description: `${type}(${key === ' ' ? 'Space' : key}): ${selector}`,
     data: {
       selector,
       eventName: type,
@@ -109,6 +112,7 @@ function keyEventListener({
         keyCode,
         shiftKey,
       },
+      description: `${type}(${key === ' ' ? 'Space' : key}): ${selector}`,
     },
   });
 }
@@ -134,8 +138,10 @@ function clickListener(event) {
 
       addBlock({
         id: 'link',
-        data: { selector },
-        description: target.href,
+        data: {
+          selector,
+          description: (target.innerText || target.href).slice(0, 64),
+        },
       });
 
       window.open(event.target.href, '_blank');
@@ -149,8 +155,12 @@ function clickListener(event) {
   addBlock({
     isClickLink,
     id: 'event-click',
-    data: { selector },
     description: elText.slice(0, 64) || selector,
+    data: {
+      selector,
+      waitForSelector: true,
+      description: elText.slice(0, 64),
+    },
   });
 }
 

+ 2 - 6
src/newtab/App.vue

@@ -214,19 +214,15 @@ window.addEventListener('beforeunload', () => {
     await Promise.allSettled([
       store.dispatch('retrieve', ['workflows', 'logs', 'collections']),
       store.dispatch('retrieveWorkflowState'),
-      loadLocaleMessages(store.state.settings.locale, 'newtab'),
     ]);
+
+    await loadLocaleMessages(store.state.settings.locale, 'newtab');
     await setI18nLanguage(store.state.settings.locale);
 
     retrieved.value = true;
 
     await fetchUserData();
     await syncHostWorkflow();
-
-    store.commit('updateState', {
-      key: 'userDataRetrieved',
-      value: true,
-    });
   } catch (error) {
     retrieved.value = true;
     console.error(error);

+ 38 - 21
src/popup/pages/Recording.vue

@@ -10,7 +10,8 @@
           class="absolute animate-ping bg-red-400 rounded-full"
           style="height: 80%; width: 80%; animation-duration: 1.3s"
         ></span>
-        <v-remixicon name="riStopLine" class="z-10 relative" />
+        <ui-spinner v-if="state.isGenerating" color="text-white" />
+        <v-remixicon v-else name="riStopLine" class="z-10 relative" />
       </button>
       <div class="ml-4 flex-1 overflow-hidden">
         <p class="text-sm">{{ t('recording.title') }}</p>
@@ -33,10 +34,10 @@
             {{ t(`workflow.blocks.${item.id}.name`) }}
           </p>
           <p
-            :title="item.description"
+            :title="item.data.description || item.description"
             class="text-overflow text-sm leading-tight text-gray-600"
           >
-            {{ item.description }}
+            {{ item.data.description || item.description }}
           </p>
         </div>
         <v-remixicon
@@ -65,6 +66,7 @@ const state = reactive({
   name: '',
   flows: [],
   activeTab: {},
+  isGenerating: false,
 });
 
 function generateDrawflow() {
@@ -134,28 +136,43 @@ function generateDrawflow() {
   return { drawflow: { Home: { data: nodes } } };
 }
 async function stopRecording() {
-  const drawflow = generateDrawflow();
+  if (state.isGenerating) return;
+  if (state.flows.length === 0) {
+    router.push('/');
+    return;
+  }
 
-  await Workflow.insert({
-    data: {
-      name: state.name,
-      drawflow: JSON.stringify(drawflow),
-    },
-  });
+  try {
+    state.isGenerating = true;
 
-  await browser.storage.local.remove(['isRecording', 'recording']);
-  await browser.browserAction.setBadgeText({ text: '' });
+    const drawflow = generateDrawflow();
 
-  const tabs = (await browser.tabs.query({})).filter((tab) =>
-    tab.url.startsWith('http')
-  );
-  await Promise.allSettled(
-    tabs.map(({ id }) =>
-      browser.tabs.sendMessage(id, { type: 'recording:stop' })
-    )
-  );
+    await Workflow.insert({
+      data: {
+        name: state.name,
+        drawflow: JSON.stringify(drawflow),
+      },
+    });
 
-  router.push('/');
+    await browser.storage.local.remove(['isRecording', 'recording']);
+    await browser.browserAction.setBadgeText({ text: '' });
+
+    const tabs = (await browser.tabs.query({})).filter((tab) =>
+      tab.url.startsWith('http')
+    );
+    await Promise.allSettled(
+      tabs.map(({ id }) =>
+        browser.tabs.sendMessage(id, { type: 'recording:stop' })
+      )
+    );
+
+    state.isGenerating = false;
+
+    router.push('/');
+  } catch (error) {
+    state.isGenerating = false;
+    console.error(error);
+  }
 }
 function removeBlock(index) {
   state.flows.splice(index, 1);