当 Electron 应用程序关闭时推送通知

时间:2021-05-16 15:58:54

标签: javascript node.js ruby-on-rails websocket electron

我的电子应用程序正在使用远程隔离方法(在 this article 中提到)。我的远程 Web 应用程序是一个 Ruby on Rails 应用程序。现在,我想使用 WebSocket 将通知从远程 Web 应用程序推送到电子应用程序。即使用户关闭了应用程序,也要向用户发送消息,我有了一个想法。在 Rails 服务器中,我使用 ActionCable 将通知广播到频道。在主要流程中,我使用 actioncable 包订阅此频道。

import ActionCable from "actioncable";

const websocketUrl = "wss://rt.custom-domain.dev/_/cable";
const cable = ActionCable.createConsumer(websocketUrl);
cable.subscriptions.create(
  { channel: "WallChannel", wall_id: "106" },
  {
    received(data: any): void {},
    disconnect(): void {},
    connected(): void {},
    disconnected(): void {},
    present(): void {},
    absent(): void {},
  }
);

但是我遇到了一个错误:

<块引用>

ReferenceError: window is not defined

然后我深入研究actioncable包的源代码,发现该包使用了浏览器的WebSocket API,所以出现错误。

我尝试使用 ws 包订阅 websocket,而不是跟随 this post。但是我无法连接到 websocket 服务器。当我调用 App.ws.sendmessage 时出现错误:

<块引用>

错误:WebSocket 未打开:readyState 0 (CONNECTING)

有没有人像我尝试过的那样使用 websocket 尝试从远程 Web 应用程序推送通知?你有没有遇到同样的问题?或者如果您对我的情况有更好的解决方案,请与我分享您的想法。非常感谢。

这是我的电子应用程序的 main.ts 文件

import { app, BrowserWindow, ipcMain, Notification } from "electron";
import { createWindow } from "src/main/CreateWindow";
import { showNotification } from "./helpers";
import appConfigs from "src/AppConfigs";

let mainWindow: BrowserWindow;

const createAppWindow = () => {
  mainWindow = createWindow(appConfigs.targetUrl, { interop: true });

  // Open the DevTools.
  if (!app.isPackaged) {
    mainWindow.webContents.openDevTools();
  }
};

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require("electron-squirrel-startup")) {
  // eslint-disable-line global-require
  app.quit();
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", () => {
  createAppWindow();
});

var App: { ws: any; param: any; connect_server: any; sendmessage: any } = {
  ws: null,
  param: null,
  connect_server: () => {},
  sendmessage: () => {},
};
App.sendmessage = function (send: any) {
  let data = {
    message: send,
    action: "speak",
  };
  let message = {
    command: "message",
    identifier: JSON.stringify(App.param),
    data: JSON.stringify(data),
  };
  App.ws.send(JSON.stringify(message));
};

App.connect_server = function () {
  const WebSocket = require("ws");

  App.ws = new WebSocket("wss://rt.custom-domain.dev/_/cable", [
    "actioncable-v1-json",
    "actioncable-unsupported",
  ]);
  console.log("connect_server", App.ws);
  App.param = { channel: "WallChannel", wall_id: 106 };

  App.ws.on("open", function open() {
    console.log("open channel");
    let data = {
      command: "subscribe",
      identifier: JSON.stringify(App.param),
    };
    App.ws.send(JSON.stringify(data));
    console.log("send JSON");
  });
  App.ws.on("message", function (event: any) {
    console.log("message", event);
  });

  App.ws.on("error", function (err) {
    console.log("Found error: " + err);
  });
};

App.connect_server();

CreateWindow.ts

import { BrowserWindow } from "electron";
import appConfigs from "src/AppConfigs";

declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: any;

interface BrowserWindowOption {
  title?: string;
  height?: string;
  width?: string;
  interop?: boolean;
}

export const createWindow = (
  url: string,
  options: BrowserWindowOption = {}
): BrowserWindow => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    title: options.title || appConfigs.name,
    height: options.height || appConfigs.height,
    width: options.width || appConfigs.width,
    webPreferences: options.interop
      ? {
          preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
        }
      : {},
  });

  // and load the targetUrl.
  mainWindow.loadURL(url || appConfigs.targetUrl);

  return mainWindow;
};

package.json

{
  "name": "electron-forge-app",
  "productName": "electron-forge-app",
  "version": "1",
  "description": "My Electron application description",
  "main": ".webpack/main",
  "scripts": {
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "publish": "electron-forge publish",
    "lint": "eslint --ext .ts ."
  },
  "keywords": [],
  "author": {
    ...
  },
  "license": "MIT",
  "config": {
    "forge": {
      "packagerConfig": {},
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "config": {
            "name": "electron_furge"
          }
        },
        {
          "name": "@electron-forge/maker-zip",
          "platforms": [
            "darwin"
          ]
        },
        {
          "name": "@electron-forge/maker-deb",
          "config": {}
        },
        {
          "name": "@electron-forge/maker-rpm",
          "config": {}
        }
      ],
      "plugins": [
        [
          "@electron-forge/plugin-webpack",
          {
            "mainConfig": "./webpack.main.config.js",
            "renderer": {
              "config": "./webpack.renderer.config.js",
              "entryPoints": [
                {
                  "html": "./src/index.html",
                  "js": "./src/renderer.ts",
                  "name": "main_window",
                  "preload": {
                    "js": "./src/interop/preload.ts"
                  }
                }
              ]
            }
          }
        ]
      ]
    }
  },
  "devDependencies": {
    "@electron-forge/cli": "^6.0.0-beta.54",
    "@electron-forge/maker-deb": "^6.0.0-beta.54",
    "@electron-forge/maker-rpm": "^6.0.0-beta.54",
    "@electron-forge/maker-squirrel": "^6.0.0-beta.54",
    "@electron-forge/maker-zip": "^6.0.0-beta.54",
    "@electron-forge/plugin-webpack": "6.0.0-beta.54",
    "@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
    "@types/actioncable": "^5.2.4",
    "@typescript-eslint/eslint-plugin": "^4.0.1",
    "@typescript-eslint/parser": "^4.0.1",
    "css-loader": "^4.2.1",
    "electron": "12.0.5",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "^2.20.0",
    "fork-ts-checker-webpack-plugin": "^5.0.14",
    "node-loader": "^1.0.1",
    "style-loader": "^1.2.1",
    "ts-loader": "^8.0.2",
    "typescript": "^4.0.2"
  },
  "dependencies": {
    "actioncable": "^5.2.6",
    "electron-squirrel-startup": "^1.0.0",
    "ws": "^7.4.5"
  }
}

0 个答案:

没有答案