Araxeus / custom-electron-prompt

Custom prompt for electron made easy with various templates
https://araxeus.github.io/custom-electron-prompt/
MIT License
14 stars 6 forks source link

Types in custom-electron-prompt #2

Open amunim opened 3 years ago

amunim commented 3 years ago

I want to use this in a typescript project and I think having types would be useful here, most of them should be imported from the original repo only the changes have to be added.

EDIT: I'm willing to add my types(the work that I added), so you don't have a burden :)

Araxeus commented 3 years ago

Ok submit a PR so that it can be tested 🙂

amunim commented 3 years ago

This is the first project I am collaborating on so I don't know how to add the types, can you explain like you did in the PR?

Araxeus commented 3 years ago

Oh I thought you already had it.

declaring types for exports might be too much since it varies so much between prompt options (function return value can be in completely different types)

maybe we should just add a custom-electron-prompt.d.ts with module declaration only and inside declare module "custom-electron-prompt"

I'm not really proficient in typescript so i'm not sure about all this. needs testing

amunim commented 3 years ago

oh I see. Anyway, there is one more problem I'm trying to solve.

The click function is converted to String which has the benefit of using document on that window but there is also a drawback... Let's say if I have a class instance in my caller file and since everything is converted to a string, the instance foo is not passed not if I call foo.bar() it doesn't exist to be called. Any ideas how should it be fixed?

Araxeus commented 3 years ago

its problematic to pass function with scopes from main process to renderer also there actually isn't much point in having this custom function converted to string etc..

there is a prompt option custom script - and you can write there an event handler for your custom button easily in that file you have access to everything as usual (renderer process - use ipc to connect to main if needed)

(just have to make sure that script is loaded after the custom button has been created - so that the script can immediately have access to that button)

https://github.com/Araxeus/custom-electron-prompt/blob/88b9a3185b687c64124438a86a740db5e85d8ea5/lib/page/prompt.js#L97-L127

amunim commented 3 years ago

Yeah, you're right. Right now I am using ipcRenderer.send in click and then replying after executing code. Basically the 'electron' way.

  click: async () => 
                    {
                       const clickPos = await new Promise<Point>(function (resolve, reject) 
                        {
                            ipcRenderer.send("clickPos", "need pos");

                            ipcRenderer.on("clickPos", (event, message) => 
                            {
                                const pos = JSON.parse(message);
                                resolve(pos);
                            });
                        });

                        (<HTMLInputElement>document.querySelectorAll("#data")[0]).value = clickPos.x.toString();
                        (<HTMLInputElement>document.querySelectorAll("#data")[1]).value = clickPos.y.toString();
                    }

and my caller class

ipcMain.on("clickPos", (event, message) => 
{
    event.reply("clickPos", JSON.stringify({x: 453, y: 674}));
    return;
}
amunim commented 3 years ago

Other that the types, can you look into this if you have some time. Thanks :)

Araxeus commented 3 years ago

I'm not sure what you are trying to do here, if you want the button to set the input fields you could use customScript and have a function like this. which is really short and nice :)

$("#custom").onclick = () => {
                 $$("#data")[0].value = "?"
                 $$("#data")[1].value = "?"
}

also in your current code - you have a memory leak - each time the button is clicked - it creates a new ipc listener and never closes it Solution: ipcRenderer.once("clickPos".. instead of ipcRenderer.on("clickPos"..

amunim commented 3 years ago

I am trying to get the position of mouse click from the user, so now each time the button is clicked it sends a message to the main class which waits for a click and then reply that position to the front. After receiving the position the X and Y are updated on the first and second input respectively. Thanks for the solution for the memory leak and I'll look into the custom script for this

Araxeus commented 3 years ago

in that case maybe something like that in customScript, which shouldn't require ipc

const getClickPos = require("./clickPos");

$("#custom").onclick = async () => {
     const clickPos = await getClickPos();
      $$("#data")[0].value = clickPos.x
      $$("#data")[1].value = clickPos.y
}
amunim commented 3 years ago

oh, great. Thanks

dubdia commented 1 week ago

Hello, i am using your prompt package in my electron typescript project and it works really well thanks for that! I just had to add this declarations file in my project:

// src/types/custom-electron-prompt.d.ts
declare module "custom-electron-prompt" {
    export interface PromptOptions {
        width?: number;
        height?: number;
        resizable?: boolean;
        title?: string;
        label?: string;
        buttonLabels?: { ok: string; cancel: string; };
        value?: string;
        type?: 'input' | 'select' | 'counter' | 'multiInput' | 'keybind';
        selectOptions?: { [key: string]: string } | string[];
        keybindOptions?: any;
        counterOptions?: {
            minimum?: number;
            maximum?: number;
            multiFire?: boolean;
        };
        icon?: string;
        useHtmlLabel?: boolean;
        customStylesheet?: string | boolean;
        menuBarVisible?: boolean;
        skipTaskbar?: boolean;
        frame?: boolean;
        customScript?: string;
        enableRemoteModule?: boolean;
    }

    // This declares that the default export of the module is this function
    export default function prompt(options: PromptOptions, parentWindow?: Electron.BrowserWindow): Promise<any>;
}

so i was able to import your prompt via import instead of require like this: import prompt from "custom-electron-prompt";

i also had to adapt my tsconfig.json and added the "types" folder to typeRoots:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "commonjs",
    "allowJs": true,
    "strict": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "noImplicitAny": true,
    "sourceMap": true,
    "baseUrl": ".",
    "outDir": "dist",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "jsx": "react-jsx",
    "typeRoots": ["./node_modules/@types", "./types"], // <- here i added types
  }
}