debarchito
debarchito

Reputation: 1335

How to use electron methods inside svelte files - Svelte 3 - or is there any other way to do that?

I've been working on a Svelte 3 + Electron 12.0.5 project. I am using the svelte-spa-router package for hash routing. My project structure looks like this:

node_modules/
public/
    build/
        bundle.css
        bundle.js
    index.html
src/
    Components/
        Pages/
            Home.svelte
            Settings.svelte
            ...
        Sidebar.svelte
        Titlebar.svelte
    App.js
    App.svelte
...
index.js // <-- Electron entry point
rollup|svelte|tailwind // <-- config files

Since I was using a router, electron's window.loadFile() was not working; To solve this, I used the sirv-cli along with concurrently. Now my start script looks like this:

"start": "concurrently \"sirv public --no-clear --port=40072\" \"electron .\""

Now I used window.loadURL("https://localhost:40072") to get this working. .svelte files, inside the <script> tags, I tried to do import * as electron from "electron"; but that resulted in a error saying fs is not defined. So for now, I created an express server inside index.js and am using using fetch to make POST request to the server and do the stuffs which I could've easily done using ipcMain and ipcRenderer...I don't know if I am doing anything wrong (nodeIntegration is already set to true). I'm kinda new to Svelte so do anyone know of any other way to use electron methods inside the script tags?

Upvotes: 5

Views: 1041

Answers (1)

debarchito
debarchito

Reputation: 1335

So, I finally solved my problem. I'm posting this as an answer so that others having the same problem can solve it. First of all, we don't need express anymore (you can also use it if you want). The start script is same i.e.

"start": "concurrently \"sirv public --no-clear --port=40072\" \"electron .\""

So instead of using nodeIntegration, we will be using preload. For e.g. lets consider a scenario of custom titlebar!

--- preload.js ---

const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld(
    "api", { // "api" --> rename it to anything you want
         titlebar: action => {
             ipcRenderer.send("titlebar", action);
         }
    }
);

--- index.js ---

const { app, ipcMain } = require("electron");
...
ipcMain.on("titlebar", (event, arg) => {
    if(arg === "destroy") window.destroy();
    else if(arg === "kill") app.quit();
    else if(arg === "minimize") window.minimize();
    else if(arg === "resize") {
       if(window.isMaximized()) window.unmaximize();
       else window.maximize();
    }
})

And finally your svelte file; consider Titlebar.svelte

<button on:click={() => window.api.titlebar("destroy")}>Destroy</button>
<button on:click={() => window.api.titlebar("kill")}>Kill</button>
<button on:click={() => window.api.titlebar("minimize")}>Minimize</button>
<button on:click={() => window.api.titlebar("resize")}>Resize</button>

This was my use-case actually. I hope it helps! Advices are appreciated!

Upvotes: 5

Related Questions