Ahmad Kholid 3 년 전
부모
커밋
5063e967dd

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "automa",
-  "version": "0.13.0",
+  "version": "0.13.2",
   "description": "An extension for automating your browser by connecting blocks",
   "license": "MIT",
   "repository": {
@@ -32,11 +32,11 @@
     "defu": "^5.0.0",
     "drawflow": "^0.0.51",
     "idb": "^7.0.0",
+    "mitt": "^3.0.0",
     "mousetrap": "^1.6.5",
     "nanoid": "3.1.28",
     "object-path-immutable": "^4.1.2",
     "papaparse": "^5.3.1",
-    "tiny-emitter": "^2.1.0",
     "tippy.js": "^6.3.1",
     "v-remixicon": "^0.1.1",
     "vue": "3.2.19",

+ 2 - 9
src/background/workflow-engine/blocks-handler/handler-conditions.js

@@ -2,9 +2,7 @@ import { getBlockConnection } from '../helper';
 import compareBlockValue from '@/utils/compare-block-value';
 import mustacheReplacer from '@/utils/reference-data/mustache-replacer';
 
-function conditions(block, { prevBlockData, refData }) {
-  const data = block.data;
-  const outputs = block.outputs
+function conditions({ data, outputs }, { prevBlockData, refData }) {
   return new Promise((resolve, reject) => {
     if (data.conditions.length === 0) {
       reject(new Error('conditions-empty'));
@@ -24,13 +22,8 @@ function conditions(block, { prevBlockData, refData }) {
       const firstValue = mustacheReplacer({
         str: compareValue ?? prevData,
         data: refData,
-        block
-      });
-      const secondValue = mustacheReplacer({
-        str: value,
-        data: refData,
-        block
       });
+      const secondValue = mustacheReplacer({ str: value, data: refData });
 
       const isMatch = compareBlockValue(type, firstValue, secondValue);
 

+ 14 - 23
src/background/workflow-engine/blocks-handler/handler-forward-page.js

@@ -1,32 +1,23 @@
 import browser from 'webextension-polyfill';
 import { getBlockConnection } from '../helper';
 
-function forwardPage(block) {
-  return new Promise((resolve, reject) => {
-    const nextBlockId = getBlockConnection(block);
+export async function goBack({ outputs }) {
+  const nextBlockId = getBlockConnection({ outputs });
 
-    if (!this.activeTab.id) {
-      const error = new Error('no-tab');
-      error.nextBlockId = nextBlockId;
+  try {
+    if (!this.activeTab.id) throw new Error('no-tab');
 
-      reject(nextBlockId);
+    await browser.tabs.goForward(this.activeTab.id);
 
-      return;
-    }
+    return {
+      data: '',
+      nextBlockId,
+    };
+  } catch (error) {
+    error.nextBlockId = nextBlockId;
 
-    browser.tabs
-      .goForward(this.activeTab.id)
-      .then(() => {
-        resolve({
-          nextBlockId,
-          data: '',
-        });
-      })
-      .catch((error) => {
-        error.nextBlockId = nextBlockId;
-        reject(error);
-      });
-  });
+    throw error;
+  }
 }
 
-export default forwardPage;
+export default goBack;

+ 13 - 22
src/background/workflow-engine/blocks-handler/handler-go-back.js

@@ -1,32 +1,23 @@
 import browser from 'webextension-polyfill';
 import { getBlockConnection } from '../helper';
 
-export function goBack(block) {
-  return new Promise((resolve, reject) => {
-    const nextBlockId = getBlockConnection(block);
+export async function goBack({ outputs }) {
+  const nextBlockId = getBlockConnection({ outputs });
 
-    if (!this.activeTab.id) {
-      const error = new Error('no-tab');
-      error.nextBlockId = nextBlockId;
+  try {
+    if (!this.activeTab.id) throw new Error('no-tab');
 
-      reject(error);
+    await browser.tabs.goBack(this.activeTab.id);
 
-      return;
-    }
+    return {
+      data: '',
+      nextBlockId,
+    };
+  } catch (error) {
+    error.nextBlockId = nextBlockId;
 
-    browser.tabs
-      .goBack(this.activeTab.id)
-      .then(() => {
-        resolve({
-          nextBlockId,
-          data: '',
-        });
-      })
-      .catch((error) => {
-        error.nextBlockId = nextBlockId;
-        reject(error);
-      });
-  });
+    throw error;
+  }
 }
 
 export default goBack;

+ 2 - 24
src/background/workflow-engine/engine.js

@@ -1,7 +1,7 @@
 import browser from 'webextension-polyfill';
 import { nanoid } from 'nanoid';
 import { tasks } from '@/utils/shared';
-import { convertData } from './helper';
+import { convertData, waitTabLoaded } from './helper';
 import { toCamelCase, parseJSON, isObject, objectHasKey } from '@/utils/helper';
 import referenceData from '@/utils/reference-data';
 import executeContentScript from './execute-content-script';
@@ -330,28 +330,6 @@ class WorkflowEngine {
   }
 
   async _sendMessageToTab(payload, options = {}) {
-    const checkActiveTab = () => {
-      return new Promise((resolve, reject) => {
-        const activeTabStatus = () => {
-          browser.tabs
-            .get(this.activeTab.id)
-            .then((tab) => {
-              if (tab.status === 'loading') {
-                setTimeout(() => {
-                  activeTabStatus();
-                }, 500);
-                return;
-              }
-
-              resolve();
-            })
-            .catch(reject);
-        };
-
-        activeTabStatus();
-      });
-    };
-
     try {
       if (!this.activeTab.id) {
         const error = new Error('no-tab');
@@ -360,7 +338,7 @@ class WorkflowEngine {
         throw error;
       }
 
-      await checkActiveTab();
+      await waitTabLoaded(this.activeTab.id);
 
       this.activeTab.frames = await executeContentScript(
         this.activeTab.id,

+ 24 - 0
src/background/workflow-engine/helper.js

@@ -1,3 +1,27 @@
+export function waitTabLoaded(tabId) {
+  return new Promise((resolve, reject) => {
+    const activeTabStatus = () => {
+      chrome.tabs.get(tabId, (tab) => {
+        if (!tab) {
+          reject(new Error('no-tab'));
+          return;
+        }
+
+        if (tab.status === 'loading') {
+          setTimeout(() => {
+            activeTabStatus();
+          }, 500);
+          return;
+        }
+
+        resolve();
+      });
+    };
+
+    activeTabStatus();
+  });
+}
+
 export function convertData(data, type) {
   let result = data;
 

+ 1 - 1
src/components/block/BlockBasic.vue

@@ -33,8 +33,8 @@
   </block-base>
 </template>
 <script setup>
-import emitter from 'tiny-emitter/instance';
 import { useI18n } from 'vue-i18n';
+import emitter from '@/lib/mitt';
 import { useEditorBlock } from '@/composable/editorBlock';
 import { useComponentId } from '@/composable/componentId';
 import BlockBase from './BlockBase.vue';

+ 8 - 14
src/components/block/BlockConditions.vue

@@ -25,15 +25,10 @@
       class="mt-4 space-y-2"
     >
       <div
-        v-for="(item, index) in block.data.conditions"
+        v-for="item in block.data.conditions"
         :key="item.id"
-        class="flex items-center group justify-end"
+        class="flex items-center justify-end"
       >
-        <v-remixicon
-          name="riDeleteBin7Line"
-          class="mr-2 cursor-pointer group-hover:visible invisible"
-          @click="deleteCondition(index)"
-        />
         <div
           class="flex items-center flex-1 p-2 bg-box-transparent rounded-lg overflow-hidden w-44"
         >
@@ -58,12 +53,13 @@
         {{ t('common.fallback') }}
       </p>
     </div>
+    <input class="trigger hidden" @change="onChange" />
   </div>
 </template>
 <script setup>
 import { watch, toRaw, onBeforeUnmount } from 'vue';
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { debounce } from '@/utils/helper';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';
@@ -79,6 +75,9 @@ const { t } = useI18n();
 const componentId = useComponentId('block-conditions');
 const block = useEditorBlock(`#${componentId}`, props.editor);
 
+function onChange({ detail }) {
+  if (detail.conditions) block.data.conditions = detail.conditions;
+}
 function editBlock() {
   emitter.emit('editor:edit-block', {
     ...block.details,
@@ -88,7 +87,7 @@ function editBlock() {
 }
 function addConditionEmit({ id }) {
   if (id !== block.id) return;
-
+  console.log(block);
   const { length } = block.data.conditions;
 
   if (length >= 10) return;
@@ -104,11 +103,6 @@ function deleteConditionEmit({ index, id }) {
   if (block.data.conditions.length === 0)
     props.editor.removeNodeOutput(block.id, `output_1`);
 }
-function deleteCondition(index) {
-  block.data.conditions.splice(index, 1);
-
-  deleteConditionEmit({ index, id: block.id });
-}
 
 watch(
   () => block.data.conditions,

+ 1 - 1
src/components/block/BlockDelay.vue

@@ -29,7 +29,7 @@
 </template>
 <script setup>
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';
 

+ 1 - 1
src/components/block/BlockElementExists.vue

@@ -35,7 +35,7 @@
 </template>
 <script setup>
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import BlockBase from './BlockBase.vue';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';

+ 1 - 1
src/components/block/BlockExportData.vue

@@ -34,7 +34,7 @@
 <script setup>
 import { useI18n } from 'vue-i18n';
 import { watch } from 'vue';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { dataExportTypes } from '@/utils/shared';
 import { debounce } from '@/utils/helper';
 import { useComponentId } from '@/composable/componentId';

+ 1 - 1
src/components/block/BlockGroup.vue

@@ -88,7 +88,7 @@ import { watch } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { nanoid } from 'nanoid';
 import draggable from 'vuedraggable';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { tasks } from '@/utils/shared';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';

+ 1 - 1
src/components/block/BlockLoopBreakpoint.vue

@@ -27,7 +27,7 @@
 </template>
 <script setup>
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';
 

+ 1 - 1
src/components/block/BlockRepeatTask.vue

@@ -37,7 +37,7 @@
 </template>
 <script setup>
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { useComponentId } from '@/composable/componentId';
 import { useEditorBlock } from '@/composable/editorBlock';
 

+ 1 - 1
src/components/newtab/workflow/WorkflowBuilder.vue

@@ -65,7 +65,7 @@ import { onMounted, shallowRef, reactive, getCurrentInstance } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { compare } from 'compare-versions';
 import defu from 'defu';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { useShortcut, getShortcut } from '@/composable/shortcut';
 import { tasks } from '@/utils/shared';
 import { parseJSON } from '@/utils/helper';

+ 18 - 7
src/components/newtab/workflow/edit/EditConditions.vue

@@ -54,9 +54,9 @@
   </div>
 </template>
 <script setup>
-import { toRef } from 'vue';
+import { ref, watch, onUnmounted } from 'vue';
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 
 const props = defineProps({
   data: {
@@ -68,7 +68,7 @@ const props = defineProps({
     default: '',
   },
 });
-defineEmits(['update:data']);
+const emit = defineEmits(['update:data']);
 
 const conditionTypes = {
   '==': 'equals',
@@ -81,7 +81,7 @@ const conditionTypes = {
 };
 const { t } = useI18n();
 
-const conditions = toRef(props.data, 'conditions');
+const conditions = ref(props.data.conditions);
 
 function getTitle(index) {
   const type = conditionTypes[conditions.value[index]?.type] || 'equals';
@@ -109,7 +109,18 @@ function deleteCondition(index) {
     id: props.blockId,
   });
 }
-// function updateData(value) {
-//   emit('update:data', { ...props.data, ...value });
-// }
+
+watch(
+  conditions,
+  () => {
+    emit('update:data', {
+      conditions: conditions.value,
+    });
+  },
+  { deep: true }
+);
+
+onUnmounted(() => {
+  emitter.off('conditions-block:delete-cond', handleDelCondition);
+});
 </script>

+ 2 - 2
src/components/ui/UiDialog.vue

@@ -35,7 +35,7 @@
 <script>
 import { reactive, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 
 export default {
   setup() {
@@ -60,7 +60,7 @@ export default {
       options: defaultOptions,
     });
 
-    emitter.on('show-dialog', (type, options) => {
+    emitter.on('show-dialog', ({ type, options }) => {
       state.type = type;
       state.input = options?.inputValue ?? '';
       state.options = {

+ 3 - 3
src/composable/dialog.js

@@ -1,12 +1,12 @@
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 
 export function useDialog() {
   function confirm(options) {
-    emitter.emit('show-dialog', 'confirm', options);
+    emitter.emit('show-dialog', { type: 'confirm', options });
   }
 
   function prompt(options) {
-    emitter.emit('show-dialog', 'prompt', options);
+    emitter.emit('show-dialog', { type: 'prompt', options });
   }
 
   return {

+ 1 - 0
src/content/element-selector/App.vue

@@ -271,6 +271,7 @@ function destroy() {
   rootElement.style.display = 'none';
 
   Object.assign(state, {
+    hide: true,
     activeTab: '',
     elSelector: '',
     isDragging: false,

+ 5 - 0
src/lib/mitt.js

@@ -0,0 +1,5 @@
+import mitt from 'mitt';
+
+const emitter = mitt();
+
+export default emitter;

+ 1 - 1
src/newtab/pages/workflows/[id].vue

@@ -149,7 +149,7 @@ import { useStore } from 'vuex';
 import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import defu from 'defu';
-import emitter from 'tiny-emitter/instance';
+import emitter from '@/lib/mitt';
 import { useDialog } from '@/composable/dialog';
 import { tasks } from '@/utils/shared';
 import { sendMessage } from '@/utils/message';

+ 1 - 1
src/utils/reference-data/mustache-replacer.js

@@ -31,7 +31,7 @@ export default function ({ str, data, block }) {
       const { dataKey, path } = keyParser(key);
       result = getObjectPath(data[dataKey], path) ?? match;
     }
-    if (block.name === 'webhook') {
+    if (block && block.name === 'webhook') {
       return JSON.stringify(result);
     }
     return typeof result === 'string' ? result : JSON.stringify(result);

+ 5 - 5
yarn.lock

@@ -4898,6 +4898,11 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
   integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
 
+mitt@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd"
+  integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==
+
 mixin-deep@^1.2.0:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -6639,11 +6644,6 @@ thunky@^1.0.2:
   resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
   integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
 
-tiny-emitter@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
-  integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
-
 tippy.js@^6.3.1:
   version "6.3.7"
   resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"