AlexTorresDev / custom-electron-titlebar

Custom electon title bar inpire on VS Code title bar
MIT License
866 stars 148 forks source link

How to use this library with the React #143

Closed raviSussol closed 2 years ago

raviSussol commented 3 years ago

Describe the bug I'd like to use this library with the React library in the electron js. I've setup the electron js with the React and I've installed this library in my project. I've tried with few approaches to load custom electron title bar in the app but it doesn't show the custom title bar when electron js app starts. Here's my attempt to load custom title bar:

CustomTitlebar.js

import React, { useEffect } from 'react';
import { Titlebar, Color } from 'custom-electron-titlebar';

/**
 *
 * @returns customized window title bar
 */
const CustomTitlebar = ({children}) => {
  const loadCustomTitlebar = async () => {
    const customTitlebar = new Titlebar();
    customTitlebar.updateBackground(Color.fromHex('#d8d8d8'));
    customTitlebar.setHorizontalAlignment = 'center';
    customTitlebar.updateTitle = 'Home - Hisab';
    return customTitlebar;
  };

  useEffect(() => {
    window.addEventListener('DOMContentLoaded', loadCustomTitlebar);
    // Clean up above functions on unmount
    return () =>  {
      window.removeEventListener('DOMContentLoaded', loadCustomTitlebar);
    }
  }, []);
  return (
    <div>{children}</div>
  );
};
export { CustomTitlebar };

App.js

import React from 'react';
import { CustomTitlebar } from './components';

const App = () => {
  return (
    <CustomTitlebar>
      <h2>Welcome to the Hisab!</h2>
    </CustomTitlebar>
  )
}

export default App;

I've also make frame: false and titleBarStyle: 'hidden' in my main process. But still the custom title bar doesn't show up when the app loads up.

Expected behavior Must show customized title bar when the app loads up.

Screenshots Screen Shot 2021-03-10 at 9 35 20 PM

Desktop (please complete the following information):

wiredmatt commented 3 years ago

Same issue here.

ericblade commented 3 years ago

I haven't tried to do anything with this in React, but my gut feel is that you're going to need useLayoutEffect() at the very least. maybe that'll get it going?

wiredmatt commented 3 years ago

Pretty sure it doesn't have to do with any hooks, since react app injects itself into a div in the template that has the id "root", before and after that it doesn't change anything of the index.html template, and I've tried adding it inside of the head tag and in the body but nothing happens.

raviSussol commented 3 years ago

@ericblade I had tried with that as well (using useLayoutEffect) but it didn't work. However, if I try using as a normal function then it loads the custom title bar. Like this:

customTitlebar.js

import React from 'react';
import { Titlebar, Color } from 'custom-electron-titlebar';

const customTitlebar = () => {
  const customTitlebar = new Titlebar();
  customTitlebar.updateBackground(Color.fromHex('#d8d8d8'));
  customTitlebar.setHorizontalAlignment = 'center';
  customTitlebar.updateTitle = 'Home - Hisab';
  return customTitlebar;
};
export { customTitlebar };

App.js

import React from 'react';
import { customTitlebar } from './components';

const App = () => {
  customTitlebar();
  return (
      <h2>Welcome!</h2>
  )
}

export default App;
wiredmatt commented 3 years ago

@raviSussol does it work as intended? Or is something not working?

raviSussol commented 3 years ago

@system32uwu No it works fine (without any issue) but I don't think this is the correct way using in React app. To be honest, I was wondering that I would use in the context so that I can share the custom title bar in every new child windows when they get opened.

ericblade commented 3 years ago

Ok, so, i'm thinking about it a little bit right now.. and.. I think that you're actually closer to correct than you think. Somewhere in your React app, probably in your index.js (or .jsx or .ts or .tsx or whatever) you're going to have a call to ReactDOM.render(, document.getElementById('root')) or something very similar to that.

As custom-electron-titlebar lives outside the part of the DOM that React is going to be monitoring, you should probably load it right about at that same spot.

wiredmatt commented 3 years ago

@ericblade I had tried with that as well (using useLayoutEffect) but it didn't work. However, if I try using as a normal function then it loads the custom title bar. Like this:

customTitlebar.js

import React from 'react';
import { Titlebar, Color } from 'custom-electron-titlebar';

const customTitlebar = () => {
  const customTitlebar = new Titlebar();
  customTitlebar.updateBackground(Color.fromHex('#d8d8d8'));
  customTitlebar.setHorizontalAlignment = 'center';
  customTitlebar.updateTitle = 'Home - Hisab';
  return customTitlebar;
};
export { customTitlebar };

App.js

import React from 'react';
import { customTitlebar } from './components';

const App = () => {
  customTitlebar();
  return (
      <h2>Welcome!</h2>
  )
}

export default App;

If I do that I get the following error:

Uncaught ReferenceError: require is not defined
    at Object.electron (index.js:60900)
    at __webpack_require__ (index.js:790)
    at fn (index.js:101)
    at Object../node_modules/custom-electron-titlebar/lib/menubar.js (index.js:18452)
    at __webpack_require__ (index.js:790)
    at fn (index.js:101)
    at Object../node_modules/custom-electron-titlebar/lib/titlebar.js (index.js:19654)
    at __webpack_require__ (index.js:790)
    at fn (index.js:101)
    at Object../node_modules/custom-electron-titlebar/lib/index.js (index.js:17562)

Which makes sense, since this should be used only in the main process, aren't you using webpack btw?

wiredmatt commented 3 years ago

Nevermind, I got it working with this options when creating the main window, in webPreferences:

webPreferences: {
      nodeIntegration: true,
      nodeIntegrationInSubFrames:true,
      nodeIntegrationInWorker:true,
      enableRemoteModule: true,
      contextIsolation:false
    }

So in index.html I have:

<body>
    <header id="titlebar">
      <script>
        const customTitlebar = require("custom-electron-titlebar");

        new customTitlebar.Titlebar({
          backgroundColor: customTitlebar.Color.fromHex("#444"),
        });
      </script>
    </header>
    <div id="root"></div>
</body>
raviSussol commented 3 years ago

@system32uwu Glad that you resolve it šŸ‘ The error you'd noticed at first for me was to set following contrainsts in the webPreferences:

- nodeIntegration: true
- contextIsolation: false
- enableRemoteModule: true

They are enough to resolve your issue. But according to the latest electron js pattern or in the latest electron version those settings are anti-pattern. Making node integration to true leads you to the security vulnerabilities as all node APIs become accessible from the renderer process which you might want to restrict/control based on your requirement only. In the latest version of the electron js contextIsolation comes with true by default to improve other security risks more details in here. So these things you may want to consider before setting above preferences for custom title bar in your app. I think this custom titlebar library may need to update along with the latest version of the electron to cope with these new changes. So I'm also not thinking to use it in my project for now (unless someone would update this library or make the React friendly - which would be awesome).

wiredmatt commented 3 years ago

Agree, I tried making my own title bar but there's no way to make it work without enabling nodeIntegration and disabling contextIsolation, I followed this.

ericblade commented 3 years ago

So I'm also not thinking to use it in my project for now (unless someone would update this library or make the React friendly

I've proposed some ideas for updating to the newer architecture patterns, but I really don't have time to rebuild an entire library :) maybe if i hit the ballmer curve one day though lol

as for making it "React friendly" i think that's not really something you can do -- the entire point of it is to be outside of the React shadow DOM. You don't want it being inside React. I think having it inside the shadow dom would be kind of pointless. (you may convince me otherwise, though :))

wiredmatt commented 3 years ago

So I'm also not thinking to use it in my project for now (unless someone would update this library or make the React friendly

I've proposed some ideas for updating to the newer architecture patterns, but I really don't have time to rebuild an entire library :) maybe if i hit the ballmer curve one day though lol

as for making it "React friendly" i think that's not really something you can do -- the entire point of it is to be outside of the React shadow DOM. You don't want it being inside React. I think having it inside the shadow dom would be kind of pointless. (you may convince me otherwise, though :))

He talked about using the state to change the title of the window and other props, so I guess that's a good point, but maybe that can be solved using a simple Githubissues.

  • Githubissues is a development platform for aggregating issues.