Browse Source

feat: add `Find tab by` selection in switch tab block

Ahmad Kholid 3 years ago
parent
commit
22a67936ac

+ 48 - 19
src/background/workflowEngine/blocksHandler/handlerSwitchTab.js

@@ -12,37 +12,66 @@ export default async function ({ data, id }) {
     return error;
   };
   this.windowId = null;
+
+  let tab = null;
   const activeTab = data.activeTab ?? true;
-  let [tab] = await browser.tabs.query({ url: data.matchPattern });
+  const findTabBy = data.findTabBy || 'match-patterns';
+  const isPrevNext = ['next-tab', 'prev-tab'].includes(findTabBy);
 
-  if (!tab) {
-    if (data.createIfNoMatch) {
-      if (!data.url.startsWith('http')) {
-        throw generateError('invalid-active-tab', { url: data.url });
-      }
+  if (!this.activeTab.id && isPrevNext) {
+    throw new Error('no-tab');
+  }
+
+  const tabs =
+    findTabBy !== 'match-patterns' ? await browser.tabs.query({}) : [];
+
+  if (findTabBy === 'match-patterns') {
+    [tab] = await browser.tabs.query({ url: data.matchPattern });
 
-      tab = await browser.tabs.create({
-        active: activeTab,
-        url: data.url,
-        windowId: this.windowId,
-      });
-    } else {
-      throw generateError('no-match-tab', { pattern: data.matchPattern });
+    if (!tab) {
+      if (data.createIfNoMatch) {
+        if (!data.url.startsWith('http')) {
+          throw generateError('invalid-active-tab', { url: data.url });
+        }
+
+        tab = await browser.tabs.create({
+          active: activeTab,
+          url: data.url,
+          windowId: this.windowId,
+        });
+      } else {
+        throw generateError('no-match-tab', { pattern: data.matchPattern });
+      }
     }
-  } else {
-    await browser.tabs.update(tab.id, { active: activeTab });
-  }
+  } else if (isPrevNext) {
+    const incrementBy = findTabBy.includes('next') ? 1 : -1;
+    let tabIndex = tabs.findIndex((item) => item.id === this.activeTab.id);
 
-  if (this.settings.debugMode) {
-    await attachDebugger(tab.id, this.activeTab.id);
-    this.debugAttached = true;
+    tabIndex += incrementBy;
+
+    if (tabIndex < 0) tabIndex = tabs.length - 1;
+    else if (tabIndex > tabs.length - 1) tabIndex = 0;
+
+    tab = tabs[tabIndex];
+  } else if (findTabBy === 'tab-index') {
+    tab = tabs[data.tabIndex];
+
+    if (!tab)
+      throw generateError(`Can't find a tab with ${data.tabIndex} index`);
   }
 
+  await browser.tabs.update(tab.id, { active: activeTab });
+
   this.activeTab.id = tab.id;
   this.activeTab.frameId = 0;
   this.activeTab.url = tab.url;
   this.windowId = tab.windowId;
 
+  if (this.settings.debugMode) {
+    await attachDebugger(tab.id, this.activeTab.id);
+    this.debugAttached = true;
+  }
+
   if (this.preloadScripts.length > 0) {
     const preloadScripts = this.preloadScripts.map((script) =>
       this._sendMessageToTab(script)

+ 67 - 40
src/components/newtab/workflow/edit/EditSwitchTab.vue

@@ -1,46 +1,67 @@
 <template>
   <div>
-    <edit-autocomplete>
-      <ui-input
-        :model-value="data.matchPattern"
-        placeholder="https://example.com/*"
-        class="w-full"
-        @change="updateData({ matchPattern: $event })"
-      >
-        <template #label>
-          {{ t('workflow.blocks.switch-tab.matchPattern') }}
-          <a
-            :title="t('common.example', 2)"
-            href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#examples"
-            target="_blank"
-            rel="noopener"
-            class="inline-block ml-1"
-          >
-            <v-remixicon
-              name="riInformationLine"
-              class="inline-block"
-              size="18"
-            />
-          </a>
-        </template>
-      </ui-input>
-    </edit-autocomplete>
-    <ui-checkbox
-      :model-value="data.createIfNoMatch"
-      class="mt-1"
-      @change="updateData({ createIfNoMatch: $event })"
+    <ui-select
+      :model-value="data.findTabBy"
+      label="Find tab by"
+      class="w-full mb-2"
+      @change="updateData({ findTabBy: $event })"
     >
-      {{ t('workflow.blocks.switch-tab.createIfNoMatch') }}
-    </ui-checkbox>
-    <edit-autocomplete v-if="data.createIfNoMatch" class="mt-2">
-      <ui-input
-        :model-value="data.url"
-        :label="t('workflow.blocks.switch-tab.url')"
-        placeholder="https://example.com"
-        class="w-full"
-        @change="updateData({ url: $event })"
-      />
-    </edit-autocomplete>
+      <option v-for="type in types" :key="type.id" :value="type.id">
+        {{ type.name }}
+      </option>
+    </ui-select>
+    <template v-if="data.findTabBy === 'match-patterns'">
+      <edit-autocomplete>
+        <ui-input
+          :model-value="data.matchPattern"
+          placeholder="https://example.com/*"
+          class="w-full"
+          @change="updateData({ matchPattern: $event })"
+        >
+          <template #label>
+            {{ t('workflow.blocks.switch-tab.matchPattern') }}
+            <a
+              :title="t('common.example', 2)"
+              href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#examples"
+              target="_blank"
+              rel="noopener"
+              class="inline-block ml-1"
+            >
+              <v-remixicon
+                name="riInformationLine"
+                class="inline-block"
+                size="18"
+              />
+            </a>
+          </template>
+        </ui-input>
+      </edit-autocomplete>
+      <ui-checkbox
+        :model-value="data.createIfNoMatch"
+        class="mt-1"
+        @change="updateData({ createIfNoMatch: $event })"
+      >
+        {{ t('workflow.blocks.switch-tab.createIfNoMatch') }}
+      </ui-checkbox>
+      <edit-autocomplete v-if="data.createIfNoMatch" class="mt-2">
+        <ui-input
+          :model-value="data.url"
+          :label="t('workflow.blocks.switch-tab.url')"
+          placeholder="https://example.com"
+          class="w-full"
+          @change="updateData({ url: $event })"
+        />
+      </edit-autocomplete>
+    </template>
+    <ui-input
+      v-else-if="data.findTabBy === 'tab-index'"
+      :model-value="data.tabIndex"
+      label="Index"
+      type="number"
+      class="w-full"
+      min="0"
+      @change="updateData({ tabIndex: +$event })"
+    />
     <ui-checkbox
       :model-value="data.activeTab"
       class="my-2"
@@ -63,6 +84,12 @@ const props = defineProps({
 const emit = defineEmits(['update:data']);
 
 const { t } = useI18n();
+const types = [
+  { id: 'match-patterns', name: 'Match patterns' },
+  { id: 'next-tab', name: 'Next tab' },
+  { id: 'prev-tab', name: 'Previous tab' },
+  { id: 'tab-index', name: 'Tab index' },
+];
 
 function updateData(value) {
   emit('update:data', { ...props.data, ...value });

+ 2 - 0
src/utils/shared.js

@@ -122,9 +122,11 @@ export const tasks = {
       disableBlock: false,
       description: '',
       url: '',
+      tabIndex: 0,
       matchPattern: '',
       activeTab: true,
       createIfNoMatch: false,
+      findTabBy: 'match-patterns',
     },
   },
   'new-window': {