Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Types in custom-electron-prompt #2

Open
amunim opened this issue May 16, 2021 · 12 comments
Open

Types in custom-electron-prompt #2

amunim opened this issue May 16, 2021 · 12 comments

Comments

@amunim
Copy link
Contributor

amunim commented May 16, 2021

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
Copy link
Owner

Araxeus commented May 16, 2021

Ok submit a PR so that it can be tested 🙂

@amunim
Copy link
Contributor Author

amunim commented May 16, 2021

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
Copy link
Owner

Araxeus commented May 16, 2021

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
Copy link
Contributor Author

amunim commented May 16, 2021

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
Copy link
Owner

Araxeus commented May 16, 2021

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)

//load custom script from options
if (promptOptions.customScript) {
try {
const customScript = require(promptOptions.customScript);
customScript();
} catch (error) {
return promptError(error);
}
}
if (promptOptions.button) {
const button = document.createElement("button");
// insert custom input attributes if in options
if (promptOptions.button.attrs && typeof (promptOptions.button.attrs) === "object") {
for (const k in promptOptions.button.attrs) {
if (!Object.prototype.hasOwnProperty.call(promptOptions.button.attrs, k)) {
continue;
}
button.setAttribute(k, promptOptions.button.attrs[k]);
}
}
button.addEventListener("click", () => eval(promptOptions.button.click));
button.innerText = promptOptions.button.label;
button.setAttribute("type", "button");
button.setAttribute("id", "custom");
buttonsContainer.prepend(button);
}
}

@amunim
Copy link
Contributor Author

amunim commented May 16, 2021

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
Copy link
Contributor Author

amunim commented May 16, 2021

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

@Araxeus
Copy link
Owner

Araxeus commented May 16, 2021

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
Copy link
Contributor Author

amunim commented May 16, 2021

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
Copy link
Owner

Araxeus commented May 16, 2021

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
Copy link
Contributor Author

amunim commented May 16, 2021

oh, great. Thanks

@dubdia
Copy link

dubdia commented Oct 11, 2024

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
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants