Skip to content

Commit

Permalink
Consolidate splash screen and full screen windows (#71)
Browse files Browse the repository at this point in the history
* Consolidate splash screen and full screen windows

* Remove open splash screen API
  • Loading branch information
sergeichestakov authored Jul 20, 2023
1 parent 64e4a73 commit e23b669
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 121 deletions.
6 changes: 3 additions & 3 deletions src/createMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {
MenuItemConstructorOptions,
} from "electron";
import { baseUrl } from "./constants";
import { createFullWindow, createSplashScreenWindow } from "./createWindow";
import { createWindow } from "./createWindow";
import { isMac } from "./platform";

const replUrlRegExp = new RegExp(`${baseUrl}/@[^/]+/.+`);

const newWindowMenuItem = {
label: "New Window",
accelerator: "CommandOrControl+Shift+N",
click: () => createSplashScreenWindow(),
click: () => createWindow(),
};

const openReplFromClipboardMenuItem = {
Expand All @@ -25,7 +25,7 @@ const openReplFromClipboardMenuItem = {
const isReplUrl = replUrlRegExp.test(clipboardText);

if (isReplUrl) {
createFullWindow({ url: clipboardText });
createWindow({ url: clipboardText });
} else {
dialog.showMessageBox({
type: "warning" as const,
Expand Down
100 changes: 26 additions & 74 deletions src/createWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,27 @@ import { events } from "./events";
import { isMac } from "./platform";
import store from "./store";

interface BaseWindowProps {
url: string;
constructorOptions?: BrowserWindowConstructorOptions;
interface WindowProps {
url?: string;
}

function createBaseWindow({
url,
constructorOptions,
}: BaseWindowProps): BrowserWindow {
export function createWindow(props?: WindowProps): BrowserWindow {
const backgroundColor = store.getLastSeenBackgroundColor();
const url = props?.url || `${baseUrl}/desktopApp/auth`;

// For MacOS we use a hidden titlebar and move the traffic lights into the header of the interface
// the corresponding CSS adjustments to enable that live in the repl-it-web repo!
const platformStyling: BrowserWindowConstructorOptions = isMac()
? {
titleBarStyle: "hidden",
titleBarOverlay: {
color: "var(--background-root)",
symbolColor: "var(--foreground-default)",
height: 60,
},
trafficLightPosition: { x: 20, y: 22 },
}
: {};

const window = new BrowserWindow({
webPreferences: {
Expand All @@ -35,7 +46,7 @@ function createBaseWindow({
icon,
backgroundColor,
autoHideMenuBar: true, // Window & Linux only, hides the menubar unless `Alt` is held
...constructorOptions,
...platformStyling,
});

// Add a custom string to user agent to make it easier to differentiate requests from desktop app
Expand Down Expand Up @@ -75,79 +86,15 @@ function createBaseWindow({
}
});

// Bypass the browser's cache when initially loading the remote URL
// in order to ensure that we load the latest web build.
// See: https://github.com/electron/electron/issues/1360#issuecomment-156506130
window.loadURL(url, { extraHeaders: "pragma: no-cache\n" });

return window;
}

interface WindowProps {
url: string;
}

export function createSplashScreenWindow(props?: WindowProps): BrowserWindow {
const url = props?.url || `${baseUrl}/desktopApp/auth`;

const window = createBaseWindow({
url,
constructorOptions: {
frame: false,
resizable: false,
minimizable: false,
maximizable: false,
fullscreen: false,
},
});

const width = 480;
const height = 640;

const bounds = {
...store.getSplashScreenWindowBounds(),
width,
height,
};

window.setBounds(bounds);

window.on("close", () => {
store.setSplashScreenWindowBounds(window.getBounds());
});

return window;
}

export function createFullWindow({ url }: WindowProps): BrowserWindow {
// For MacOS we use a hidden titlebar and move the traffic lights into the header of the interface
// the corresponding CSS adjustments to enable that live in the repl-it-web repo!
const platformStyling: BrowserWindowConstructorOptions = isMac()
? {
titleBarStyle: "hidden",
titleBarOverlay: {
color: "var(--background-root)",
symbolColor: "var(--foreground-default)",
height: 60,
},
trafficLightPosition: { x: 20, y: 22 },
}
: {};

const window = createBaseWindow({
url,
constructorOptions: platformStyling,
});

window.setBounds(store.getFullWindowBounds());
window.setBounds(store.getWindowBounds());

window.on("close", async () => {
// We're capturing the background color to use as main browser window background color.
const backgroundColor = await window.webContents.executeJavaScript(
`getComputedStyle(document.body).getPropertyValue('--background-root');`
);
store.setLastSeenBackgroundColor(backgroundColor);
store.setFullWindowBounds(window.getBounds());
store.setWindowBounds(window.getBounds());
});

window.on("enter-full-screen", () => {
Expand All @@ -158,5 +105,10 @@ export function createFullWindow({ url }: WindowProps): BrowserWindow {
window.webContents.send(events.ON_LEAVE_FULLSCREEN);
});

// Bypass the browser's cache when initially loading the remote URL
// in order to ensure that we load the latest web build.
// See: https://github.com/electron/electron/issues/1360#issuecomment-156506130
window.loadURL(url, { extraHeaders: "pragma: no-cache\n" });

return window;
}
4 changes: 2 additions & 2 deletions src/deeplink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { app, BrowserWindow } from "electron";
import { isWindows, isLinux } from "./platform";
import { baseUrl, protocol } from "./constants";
import path from "path";
import { createSplashScreenWindow } from "./createWindow";
import { createWindow } from "./createWindow";
import { events } from "./events";

export function registerDeeplinkProtocol(): void {
Expand Down Expand Up @@ -62,7 +62,7 @@ function handleAuthComplete(authToken: string) {
if (!authWindow) {
const url = `${authUrl}?authToken=${authToken}`;

createSplashScreenWindow({
createWindow({
url,
});

Expand Down
1 change: 0 additions & 1 deletion src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export enum events {
CLOSE_CURRENT_WINDOW = "CLOSE_CURRENT_WINDOW",
AUTH_TOKEN_RECEIVED = "AUTH_TOKEN_RECEIVED",
OPEN_REPL_WINDOW = "OPEN_REPL_WINDOW",
OPEN_SPLASH_SCREEN_WINDOW = "OPEN_SPLASH_SCREEN_WINDOW",
OPEN_EXTERNAL_URL = "OPEN_EXTERNAL_URL",
LOGOUT = "LOGOUT",
ON_ENTER_FULLSCREEN = "ON_ENTER_FULLSCREEN",
Expand Down
10 changes: 3 additions & 7 deletions src/ipc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BrowserWindow, ipcMain, shell } from "electron";
import { createFullWindow, createSplashScreenWindow } from "./createWindow";
import { createWindow } from "./createWindow";
import { baseUrl } from "./constants";
import { events } from "./events";

Expand All @@ -21,11 +21,7 @@ export function setIpcEventListeners(): void {

ipcMain.on(events.OPEN_REPL_WINDOW, (_, replSlug) => {
const url = `${baseUrl}${replSlug}`;
createFullWindow({ url });
});

ipcMain.on(events.OPEN_SPLASH_SCREEN_WINDOW, () => {
createSplashScreenWindow();
createWindow({ url });
});

ipcMain.on(events.OPEN_EXTERNAL_URL, (_, url) => {
Expand All @@ -37,6 +33,6 @@ export function setIpcEventListeners(): void {
const url = `${baseUrl}/logout?goto=/desktopApp/auth`;

BrowserWindow.getAllWindows().forEach((win) => win.close());
createSplashScreenWindow({ url });
createWindow({ url });
});
}
6 changes: 3 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { app, Menu, BrowserWindow } from "electron";
import { createSplashScreenWindow } from "./createWindow";
import { createWindow } from "./createWindow";
import { appName, macAppIcon } from "./constants";
import { isMac } from "./platform";
import { initSentry } from "./sentry";
Expand Down Expand Up @@ -41,14 +41,14 @@ app.whenReady().then(() => {

setOpenDeeplinkListeners();
setIpcEventListeners();
createSplashScreenWindow();
createWindow();
checkForUpdates();

app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createSplashScreenWindow();
createWindow();
}
});
});
Expand Down
2 changes: 0 additions & 2 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ contextBridge.exposeInMainWorld("replitDesktop", {
closeCurrentWindow: () => ipcRenderer.send(events.CLOSE_CURRENT_WINDOW),
openReplWindow: (replSlug: string) =>
ipcRenderer.send(events.OPEN_REPL_WINDOW, replSlug),
openSplashScreenWindow: () =>
ipcRenderer.send(events.OPEN_SPLASH_SCREEN_WINDOW),
openExternalUrl: (url: string) =>
ipcRenderer.send(events.OPEN_EXTERNAL_URL, url),
onAuthTokenReceived: (callback: (token: string) => void) => {
Expand Down
34 changes: 5 additions & 29 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import Store from "electron-store";

const keys = {
LAST_SEEN_BACKGROUND_COLOR: "LAST_SEEN_BACKGROUND_COLOR",
SPLASH_SCREEN_WINDOW_BOUNDS: "SPLASH_SCREEN_WINDOW_BOUNDS",
FULL_WINDOW_BOUNDS: "FULL_WINDOW_BOUNDS",
WINDOW_BOUNDS: "WINDOW_BOUNDS",
};

// var(--background-root) value for dark mode
Expand All @@ -23,39 +22,16 @@ function createStore() {
defaultBgColor
) as string;
},
setFullWindowBounds(bounds: Rectangle) {
store.set(keys.FULL_WINDOW_BOUNDS, bounds);
setWindowBounds(bounds: Rectangle) {
store.set(keys.WINDOW_BOUNDS, bounds);
},
getFullWindowBounds(): Rectangle {
getWindowBounds(): Rectangle {
// We're assuming that the active screen is the one with the mouse cursor.
// This fixes the bug where opening a Repl from a Splash Screen opens it on some other display.
const mousePosition = screen.getCursorScreenPoint();
const mouseScreen = screen.getDisplayNearestPoint(mousePosition);

return store.get(
keys.FULL_WINDOW_BOUNDS,
mouseScreen.workArea
) as Rectangle;
},
setSplashScreenWindowBounds(bounds: Rectangle) {
store.set(keys.SPLASH_SCREEN_WINDOW_BOUNDS, bounds);
},
getSplashScreenWindowBounds(): Rectangle {
const { workArea } = screen.getPrimaryDisplay();
const width = 480;
const height = 640;

const defaultBounds = {
x: Math.round(workArea.width / 2 - width / 2),
y: Math.round(workArea.height / 2 - height / 2),
width,
height,
};

return store.get(
keys.SPLASH_SCREEN_WINDOW_BOUNDS,
defaultBounds
) as Rectangle;
return store.get(keys.WINDOW_BOUNDS, mouseScreen.workArea) as Rectangle;
},
};
}
Expand Down

0 comments on commit e23b669

Please sign in to comment.