Bladeren bron

feat: show notification after running workflow

Ahmad Kholid 3 jaren geleden
bovenliggende
commit
f6a40d8ec1

+ 3 - 0
.eslintrc.js

@@ -28,6 +28,9 @@ module.exports = {
     },
   },
   // add your custom rules here
+  globals: {
+    BROWSER_TYPE: true,
+  },
   rules: {
     camelcase: 'off',
     'no-await-in-loop': 'off',

+ 32 - 2
src/background/index.js

@@ -91,6 +91,25 @@ const workflow = {
       engine.resume(options.state);
     } else {
       engine.init();
+
+      engine.on('destroyed', ({ id, status }) => {
+        browser.permissions
+          .contains({ permissions: ['notifications'] })
+          .then((hasPermission) => {
+            if (!hasPermission || !workflowData.settings.notification) return;
+
+            const name = workflowData.name.slice(0, 32);
+
+            browser.notifications.create(`logs:${id}`, {
+              type: 'basic',
+              iconUrl: browser.runtime.getURL('icon-128.png'),
+              title: status === 'success' ? 'Success' : 'Error',
+              message: `${
+                status === 'success' ? 'Successfully' : 'Failed'
+              } to run the "${name}" workflow`,
+            });
+          });
+      });
     }
 
     return engine;
@@ -315,8 +334,10 @@ browser.alarms.onAlarm.addListener(async ({ name }) => {
   }
 });
 
-if (browser.contextMenus && browser.contextMenus.onClicked) {
-  browser.contextMenus.onClicked.addListener(
+const contextMenu =
+  BROWSER_TYPE === 'firefox' ? browser.menus : browser.contextMenus;
+if (contextMenu && contextMenu.onClicked) {
+  contextMenu.onClicked.addListener(
     async ({ parentMenuItemId, menuItemId }, tab) => {
       try {
         if (parentMenuItemId !== 'automaContextMenu') return;
@@ -339,6 +360,15 @@ if (browser.contextMenus && browser.contextMenus.onClicked) {
   );
 }
 
+if (browser.notifications && browser.notifications.onClicked) {
+  browser.notifications.onClicked.addListener((notificationId) => {
+    if (notificationId.startsWith('logs')) {
+      const { 1: logId } = notificationId.split(':');
+      openDashboard(`/logs/${logId}`);
+    }
+  });
+}
+
 browser.runtime.onInstalled.addListener(async ({ reason }) => {
   try {
     if (reason === 'install') {

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

@@ -72,6 +72,7 @@ const activeTab = ref('general');
 const settings = reactive({
   publicId: '',
   restartTimes: 3,
+  notification: true,
   tabLoadTimeout: 30000,
   inputAutocomplete: true,
   insertDefaultColumn: true,

+ 27 - 1
src/components/newtab/workflow/settings/SettingsGeneral.vue

@@ -32,6 +32,30 @@
       </span>
     </div>
   </div>
+  <div class="flex items-center pt-4">
+    <div class="mr-4 flex-1">
+      <p>
+        {{ t('workflow.settings.notification.title') }}
+      </p>
+      <p class="text-gray-600 dark:text-gray-200 text-sm leading-tight">
+        {{
+          t(
+            `workflow.settings.notification.${
+              permissions.has.notifications ? 'description' : 'noPermission'
+            }`
+          )
+        }}
+      </p>
+    </div>
+    <ui-switch
+      v-if="permissions.has.notifications"
+      :model-value="settings.notification"
+      @change="updateSetting('notification', $event)"
+    />
+    <ui-button v-else @click="permissions.request">
+      {{ t('workflow.blocks.clipboard.grantPermission') }}
+    </ui-button>
+  </div>
   <div
     v-for="item in settingItems"
     :key="item.id"
@@ -94,8 +118,9 @@
 import { useI18n } from 'vue-i18n';
 import { useToast } from 'vue-toastification';
 import { clearCache } from '@/utils/helper';
+import { useHasPermissions } from '@/composable/hasPermissions';
 
-defineProps({
+const props = defineProps({
   settings: {
     type: Object,
     default: () => ({}),
@@ -105,6 +130,7 @@ const emit = defineEmits(['update']);
 
 const { t } = useI18n();
 const toast = useToast();
+const permissions = useHasPermissions(['notifications']);
 
 const browserType = BROWSER_TYPE;
 const onError = [

+ 5 - 0
src/locales/en/newtab.json

@@ -196,6 +196,11 @@
     "settings": {
       "saveLog": "Save workflow log",
       "executedBlockOnWeb": "Show executed block on web page",
+      "notification": {
+        "title": "Workflow notification",
+        "description": "Show workflow status(success or failed) after it executed",
+        "noPermission": "Automa requires \"notifications\" permission to make this work"
+      },
       "publicId": {
         "title": "Workflow public Id",
         "description": "Use this public id to execute workflow using JS custom event"

+ 2 - 1
src/manifest.chrome.json

@@ -48,7 +48,8 @@
   "optional_permissions": [
     "clipboardRead",
     "downloads",
-    "contextMenus"
+    "contextMenus",
+    "notifications"
   ],
   "permissions": [
     "tabs",

+ 2 - 1
src/manifest.firefox.json

@@ -52,7 +52,8 @@
   "optional_permissions": [
     "clipboardRead",
     "downloads",
-    "menus"
+    "menus",
+    "notifications"
   ],
   "permissions": [
     "tabs",

+ 1 - 0
src/models/workflow.js

@@ -36,6 +36,7 @@ class Workflow extends Model {
         saveLog: true,
         debugMode: false,
         restartTimes: 3,
+        notification: true,
         reuseLastState: false,
         inputAutocomplete: true,
         onError: 'stop-workflow',

+ 1 - 2
src/utils/handleFormElement.js

@@ -52,10 +52,9 @@ function formEvent(element, data) {
 async function inputText({ data, element, isEditable }) {
   const elementKey = isEditable ? 'textContent' : 'value';
 
-  if (data.delay > 0) {
+  if (data.delay > 0 && !document.hidden) {
     for (let index = 0; index < data.value.length; index += 1) {
       const currentChar = data.value[index];
-
       element[elementKey] += currentChar;
 
       if (elementKey === 'value') reactJsEvent(element, element.value);