Browse Source

feat: add "Wait till tab loaded" option in the new tab block

Ahmad Kholid 3 years ago
parent
commit
4a64c1811d

+ 1 - 1
src/background/workflowEngine/blocksHandler/handlerConditions.js

@@ -33,7 +33,7 @@ async function conditions({ data, outputs }, { prevBlockData, refData }) {
       );
 
       Object.assign(replacedValue, result?.replacedValue || {});
-      console.log(result);
+
       if (result.isMatch) {
         isConditionMatch = true;
         outputIndex = index + 1;

+ 29 - 19
src/background/workflowEngine/blocksHandler/handlerNewTab.js

@@ -1,12 +1,13 @@
 import browser from 'webextension-polyfill';
 import { isWhitespace, sleep } from '@/utils/helper';
 import {
-  getBlockConnection,
+  waitTabLoaded,
   attachDebugger,
   sendDebugCommand,
+  getBlockConnection,
 } from '../helper';
 
-async function newTab(block) {
+async function newTab({ outputs, data }) {
   if (this.windowId) {
     try {
       await browser.windows.get(this.windowId);
@@ -15,18 +16,16 @@ async function newTab(block) {
     }
   }
 
-  const nextBlockId = getBlockConnection(block);
+  const nextBlockId = getBlockConnection({ outputs });
 
   try {
-    const { updatePrevTab, url, active, inGroup, customUserAgent, userAgent } =
-      block.data;
-    const isInvalidUrl = !/^https?/.test(url);
+    const isInvalidUrl = !/^https?/.test(data.url);
 
     if (isInvalidUrl) {
       const error = new Error(
-        isWhitespace(url) ? 'url-empty' : 'invalid-active-tab'
+        isWhitespace(data.url) ? 'url-empty' : 'invalid-active-tab'
       );
-      error.data = { url };
+      error.data = { url: data.url };
 
       throw error;
     }
@@ -34,25 +33,28 @@ async function newTab(block) {
     let tab = null;
     const isChrome = BROWSER_TYPE === 'chrome';
 
-    if (updatePrevTab && this.activeTab.id) {
-      tab = await browser.tabs.update(this.activeTab.id, { url, active });
+    if (data.updatePrevTab && this.activeTab.id) {
+      tab = await browser.tabs.update(this.activeTab.id, {
+        url: data.url,
+        active: data.active,
+      });
     } else {
       tab = await browser.tabs.create({
-        url,
-        active,
+        url: data.url,
+        active: data.active,
         windowId: this.windowId,
       });
     }
 
-    this.activeTab.url = url;
+    this.activeTab.url = data.url;
     if (tab) {
-      if (this.settings.debugMode || customUserAgent) {
+      if (this.settings.debugMode || data.customUserAgent) {
         await attachDebugger(tab.id, this.activeTab.id);
         this.debugAttached = true;
 
-        if (customUserAgent && isChrome) {
+        if (data.customUserAgent && isChrome) {
           await sendDebugCommand(tab.id, 'Network.setUserAgentOverride', {
-            userAgent,
+            userAgent: data.userAgent,
           });
           await browser.tabs.reload(tab.id);
           await sleep(1000);
@@ -63,7 +65,7 @@ async function newTab(block) {
       this.windowId = tab.windowId;
     }
 
-    if (inGroup && !updatePrevTab) {
+    if (data.inGroup && !data.updatePrevTab) {
       const options = {
         groupId: this.activeTab.groupId,
         tabIds: this.activeTab.id,
@@ -84,7 +86,7 @@ async function newTab(block) {
 
     this.activeTab.frameId = 0;
 
-    if (isChrome && !this.settings.debugMode && customUserAgent) {
+    if (isChrome && !this.settings.debugMode && data.customUserAgent) {
       chrome.debugger.detach({ tabId: tab.id });
     }
 
@@ -95,9 +97,17 @@ async function newTab(block) {
       await Promise.allSettled(preloadScripts);
     }
 
+    console.log(data, data.waitTabLoaded);
+    if (data.waitTabLoaded) {
+      await waitTabLoaded(
+        this.activeTab.id,
+        this.settings?.tabLoadTimeout ?? 30000
+      );
+    }
+
     return {
-      data: url,
       nextBlockId,
+      data: data.url,
     };
   } catch (error) {
     error.nextBlockId = nextBlockId;

+ 5 - 1
src/components/newtab/workflow/WorkflowSettings.vue

@@ -23,7 +23,11 @@
       style="height: calc(100vh - 10rem); max-height: 600px"
     >
       <ui-tab-panel v-for="tab in tabs" :key="tab.value" :value="tab.value">
-        <component :is="tab.component" :settings="settings" />
+        <component
+          :is="tab.component"
+          :settings="settings"
+          @update="settings[$event.key] = $event.value"
+        />
       </ui-tab-panel>
     </ui-tab-panels>
   </ui-card>

+ 8 - 0
src/components/newtab/workflow/edit/EditNewTab.vue

@@ -24,6 +24,14 @@
     >
       {{ t('workflow.blocks.new-tab.updatePrevTab.text') }}
     </ui-checkbox>
+    <ui-checkbox
+      :model-value="data.waitTabLoaded"
+      class="leading-tight mt-2"
+      :title="t('workflow.blocks.new-tab.waitTabLoaded')"
+      @change="updateData({ waitTabLoaded: $event })"
+    >
+      {{ t('workflow.blocks.new-tab.waitTabLoaded') }}
+    </ui-checkbox>
     <ui-checkbox
       :model-value="data.active"
       class="my-2"

+ 51 - 0
src/components/newtab/workflow/settings/SettingsBlocks.vue

@@ -0,0 +1,51 @@
+<template>
+  <div class="flex items-center">
+    <div class="mr-4 flex-1">
+      <p>
+        {{ t('workflow.settings.blockDelay.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ t('workflow.settings.blockDelay.description') }}
+      </p>
+    </div>
+    <ui-input
+      :model-value="settings.blockDelay"
+      type="number"
+      @change="updateSetting('blockDelay', +$event)"
+    />
+  </div>
+  <div class="flex items-center pt-4">
+    <div class="mr-4 flex-1">
+      <p>
+        {{ t('workflow.settings.tabLoadTimeout.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ t('workflow.settings.tabLoadTimeout.description') }}
+      </p>
+    </div>
+    <ui-input
+      :model-value="settings.tabLoadTimeout"
+      type="number"
+      min="0"
+      max="60000"
+      @change="updateSetting('tabLoadTimeout', +$event)"
+    />
+  </div>
+</template>
+<script setup>
+import { useI18n } from 'vue-i18n';
+
+defineProps({
+  settings: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const emit = defineEmits(['update']);
+
+const { t } = useI18n();
+
+function updateSetting(key, value) {
+  emit('update', { key, value });
+}
+</script>

+ 145 - 0
src/components/newtab/workflow/settings/SettingsGeneral.vue

@@ -0,0 +1,145 @@
+<template>
+  <div class="flex items-center">
+    <div class="mr-4 flex-1">
+      <p>
+        {{ t('workflow.settings.onError.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ t('workflow.settings.onError.description') }}
+      </p>
+    </div>
+    <ui-select
+      :model-value="settings.onError"
+      @change="updateSetting('onError', $event)"
+    >
+      <option v-for="item in onError" :key="item.id" :value="item.id">
+        {{ t(`workflow.settings.onError.items.${item.name}`) }}
+      </option>
+    </ui-select>
+    <div
+      v-if="settings.onError === 'restart-workflow'"
+      :title="t('workflow.settings.restartWorkflow.description')"
+      class="flex items-center bg-input transition-colors rounded-lg ml-4"
+    >
+      <input
+        :value="settings.restartTimes ?? 3"
+        type="number"
+        class="py-2 pl-2 text-right appearance-none w-12 rounded-lg bg-transparent"
+        @input="updateSetting('restartTimes', +($event.target.value ?? 3))"
+      />
+      <span class="px-2 text-sm">
+        {{ t('workflow.settings.restartWorkflow.times') }}
+      </span>
+    </div>
+  </div>
+  <div
+    v-for="item in settingItems"
+    :key="item.id"
+    class="flex items-center pt-4"
+  >
+    <div class="mr-4 flex-1">
+      <p>
+        {{ item.name }}
+      </p>
+      <p
+        v-if="item.notSupport?.includes(browserType)"
+        class="text-sm leading-tight text-red-400 dark:text-red-300"
+      >
+        {{
+          t('log.messages.browser-not-supported', {
+            browser: browserType,
+          })
+        }}
+      </p>
+      <p v-else class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ item.description }}
+      </p>
+    </div>
+    <ui-switch
+      v-if="!item.notSupport?.includes(browserType)"
+      :model-value="settings[item.id]"
+      @change="updateSetting(item.id, $event)"
+    />
+  </div>
+  <div class="flex items-center pt-4">
+    <div class="mr-4 flex-1">
+      <p>
+        {{ t('workflow.settings.clearCache.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ t('workflow.settings.clearCache.description') }}
+      </p>
+    </div>
+    <ui-button @click="onClearCacheClick">
+      {{ t('workflow.settings.clearCache.btn') }}
+    </ui-button>
+  </div>
+</template>
+<script setup>
+import { useI18n } from 'vue-i18n';
+import { useToast } from 'vue-toastification';
+import { clearCache } from '@/utils/helper';
+
+defineProps({
+  settings: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const emit = defineEmits(['update']);
+
+const { t } = useI18n();
+const toast = useToast();
+
+const browserType = BROWSER_TYPE;
+const onError = [
+  {
+    id: 'keep-running',
+    name: 'keepRunning',
+  },
+  {
+    id: 'stop-workflow',
+    name: 'stopWorkflow',
+  },
+  {
+    id: 'restart-workflow',
+    name: 'restartWorkflow',
+  },
+];
+const settingItems = [
+  {
+    id: 'debugMode',
+    notSupport: ['firefox'],
+    name: t('workflow.settings.debugMode.title'),
+    description: t('workflow.settings.debugMode.description'),
+  },
+  {
+    id: 'inputAutocomplete',
+    name: t('workflow.settings.autocomplete.title'),
+    description: t('workflow.settings.autocomplete.description'),
+  },
+  {
+    id: 'reuseLastState',
+    name: t('workflow.settings.reuseLastState.title'),
+    description: t('workflow.settings.reuseLastState.description'),
+  },
+  {
+    id: 'saveLog',
+    name: t('workflow.settings.saveLog'),
+    description: '',
+  },
+  {
+    id: 'executedBlockOnWeb',
+    name: t('workflow.settings.executedBlockOnWeb'),
+    description: '',
+  },
+];
+
+async function onClearCacheClick() {
+  const cacheCleared = await clearCache(props.workflow);
+  if (cacheCleared) toast(t('workflow.settings.clearCache.info'));
+}
+function updateSetting(key, value) {
+  emit('update', { key, value });
+}
+</script>

+ 45 - 0
src/components/newtab/workflow/settings/SettingsTable.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="flex items-center">
+    <div class="flex-grow">
+      <p>
+        {{ t('workflow.settings.defaultColumn.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{ t('workflow.settings.defaultColumn.description') }}
+      </p>
+    </div>
+    <ui-switch
+      :model-value="settings.insertDefaultColumn"
+      @change="updateSetting('insertDefaultColumn', $event)"
+    />
+  </div>
+  <transition-expand>
+    <div v-if="settings.insertDefaultColumn" class="flex pt-4 items-center">
+      <p class="flex-1">
+        {{ t('workflow.settings.defaultColumn.name') }}
+      </p>
+      <ui-input
+        :model-value="settings.defaultColumnName"
+        :title="t('workflow.settings.defaultColumn.name')"
+        @change="updateSetting('defaultColumnName', $event)"
+      />
+    </div>
+  </transition-expand>
+</template>
+<script setup>
+import { useI18n } from 'vue-i18n';
+
+defineProps({
+  settings: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const emit = defineEmits(['update']);
+
+const { t } = useI18n();
+
+function updateSetting(key, value) {
+  emit('update', { key, value });
+}
+</script>

+ 1 - 0
src/locales/en/blocks.json

@@ -359,6 +359,7 @@
         "customUserAgent": "Use custom User-Agent",
         "activeTab": "Set as active tab",
         "tabToGroup": "Add tab to group",
+        "waitTabLoaded": "Wait till tab loaded",
         "updatePrevTab": {
           "title": "Use the previously opened new tab instead of creating a new one",
           "text": "Update previously opened tab"

+ 1 - 1
src/locales/en/newtab.json

@@ -238,7 +238,7 @@
       },
       "tabLoadTimeout": {
         "title": "Tab load timeout",
-        "description": "Maximum time to load tab in milliseconds, defaults to 30 seconds, pass 0 to disable the timeout."
+        "description": "Maximum time to load tab in milliseconds, pass 0 to disable the timeout."
       },
     }
   },

+ 1 - 0
src/utils/shared.js

@@ -82,6 +82,7 @@ export const tasks = {
       userAgent: '',
       active: true,
       inGroup: false,
+      waitTabLoaded: false,
       updatePrevTab: false,
       customUserAgent: false,
     },