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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for opening notes in new windows. Fixes #69 #83

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

derekbeau
Copy link

@klauscfhq I went ahead and attempted to add this feature since it's something I could use when on Ubuntu. This is my first time working with Electron, so comments and suggestions are requested.

I read/scanned through the documentation, then gave it a try. I may have missed something that I'm unaware of with window management (see Questions below), but my tests looked promising. They behave as expected for macOS close/quit behavior, respecting mainWindow as the main window.

Let me know what changes you would like to see before considering a merge and I'll be happy to make them 馃憤


Tested on: macOS 10.13.4 and Ubuntu 18.04. (I don't currently have a Windows environment set up to test this on).

  • Added "New Window" button to top of note frames. Decided against adding to the notes sidebar because that would require adding several elements with event listeners to the DOM.
  • Changed menu.js actions to affect the focused window.
  • Refactored createMainWIndow() into New, Main, and Sub variations.
  • New windows open at (50, -50) offset from the window that spawned it.
  • New windows open with a width that approximates the mainWindow note frame (subtracting the sidebar widths).
  • New windows auto hide the sidebar to be consistent with the native desktop apps.
  • Went with show: true immediately on new windows because waiting for them to be ready still produced a momentary blank window and the lag time from click to open could cause people to click multiple times.

Fix

  • Changed ipcMain.on('export-as-pdf') to get title from noteWindow rather than global mainWindow

Potential Changes/Additions

  • Set window title to note title. This would be better usability in OS window lists.
  • Add a draggable region when sidebar is hidden on macOS. Currently have to exit focus mode to move the note window. This problem doesn't exist on Ubuntu where the window chrome is present.
  • Use an icon instead of the "New Window" button

Omissions

  • Toggling the theme only changes the focused window. Any new windows inherit the last set theme. This could be seen as a feature, allowing the user to choose a theme for each note window. The alternative, if I'm not mistaken, would be to loop through all windows during a toggle.

Questions

  • When a new window is opened, the spawning window is sent two close events with wasClean: true, but then followed by Unrecoverable close condition, not retrying. This doesn't seem to affect the functionality, but worth bringing up. Any suggestions on this?

Copy link
Owner

@klaudiosinani klaudiosinani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! A couple of changes and it is good to be merged : )

// Add new window button to the note frame
function addNewWindowButton() {
const span = document.createElement('span');
span.appendChild(document.createTextNode('New Window'));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to change the text to something like Open Note, so it can more be more intuitive:

span.appendChild(document.createTextNode('Open Note'));

span.appendChild(document.createTextNode('New Window'));
span.setAttribute('class', 'GJDCG5CBD GJDCG5CNOB');

const div = document.createElement('div');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice!

}
}
});
const tuskWindow = new electron.BrowserWindow(Object.assign(defaultOptions, options));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we can avoid to directly override the defaultOptions object, and use it along with options to merge them against an empty object target:

const tuskWindow = new BrowserWindow(Object.assign({}, defaultOptions, options));

This way, after the merge, defaultOptions with still hold its original attributes.

return tuskWindow;
}

function createSubWindow(url, options) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we can remove options = options || {};, and do the same as before:

function createSubWindow(url, options = {}) {

function createSubWindow(url, options) {
options = options || {};
const id = subWindows.length;
const tuskWindow = createNewWindow(url, Object.assign(options, {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tuskWindow assignment can be reduced to only one line:

const tuskWindow = createNewWindow(url, Object.assign(options, {show: true}));

// Put notes opened in a new window into focus mode
ipcMain.on('note-frame-loaded', event => {
if (event.sender !== mainWindow.webContents) {
event.sender.send('focus-mode');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating a new note window in focus-mode, which can be easily untoggled by the user, we can create a new event, e.g new-window, that once fired both the sidebar and notes-list are completely removed from the UI using simple css, thus achieving a more native-feeling experience:

// Changes on `index.js`
ipcMain.on('note-frame-loaded', event => {
  if (event.sender !== mainWindow.webContents) {
    event.sender.send('new-window');
  }
});
// Addition to `browser.js`
// Activates the appropriate class names
ipc.on('new-window', () => {  document.documentElement.classList.toggle('new-window', true);}); 
/* Additions to `style/browser.css` */
div#tusk-new-window { /* Minor positioning tweak for the new button */
  margin-right: 8px;
}
.GJDCG5CBNB { /* Also, minor positioning tweak for the new button */
  display: none !important;
}
html.new-window div#gwt-debug-sidebar, html.new-window div#gwt-debug-notesListView, html.new-window div#tusk-new-window { /* Hides both the sidebar & notes-list */
  display: none !important;
}
html.new-window div#gwt-debug-stage, html.new-window div#gwt-debug-NoteView-root { /* Removes the left margin left behind by the hidden sidebar */
  margin-left: 0px !important;
}

// Open a sub window, offset from calling window
// Set width equal to the approximate note frame in main window
ipcMain.on('open-sub-window', event => {
const noteWindow = BrowserWindow.fromWebContents(event.sender);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can create the new note window based on the dimension of the user's display/work-area size, thus always achieving the same window:screen ratio, regardless of the hardware. In adddtion, instead of using indices, we can use array destructuring in order to get the x & y window coordinates, and also we can provide the window with a new unique title, instead of calling it Tusk, using the name of the note as main identifying element:

// New `ipcMain.on('open-sub-window')`
ipcMain.on('open-sub-window', event => {
  const {workAreaSize} = electron.screen.getPrimaryDisplay();
  const {width: screenWidth, height: screenHeight} = workAreaSize;

  const noteWindow = BrowserWindow.fromWebContents(event.sender);
  const [x, y] = noteWindow.getPosition();

  const noteTitle = noteWindow.webContents.getTitle().replace(' | Evernote Web', '');

  const options = {
    x: x + 50,
    y: y - 50,
    title: `${app.getName()} - ${noteTitle}`,
    width: Math.round((screenWidth * 3) / 5),
    height: Math.round((screenHeight * 3) / 5)
  };

  subWindows.push(createSubWindow(noteWindow.webContents.getURL(), options));
});

@@ -40,13 +41,12 @@ if (functioning) {
app.quit();
}

function createMainWindow() {
function createNewWindow(url, options) {
options = options || {};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here options = options || {}; can be removed and set a default value {} for the options argument at the method definition:

function createNewWindow(url, options = {}) {

@derekbeau
Copy link
Author

Thanks for taking the time to review, @klauscfhq. I'll make the changes this weekend or early next week and update the PR here. 馃憤

@markusberg-spt
Copy link

Can't wait for this feature! Is it going to be merged?

@Nemobil
Copy link

Nemobil commented Jun 25, 2021

What is the status of this feature? Has anything changed within the last 3 years? Unfortunately, this missing feature is a show stopper for me... Any chance that it will be implemented/merged?

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

Successfully merging this pull request may close these issues.

None yet

4 participants