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

[WS-31] windows integrated titlebar #102

Merged
merged 12 commits into from
Aug 23, 2023
Merged
66 changes: 37 additions & 29 deletions src/createWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import log from 'electron-log/main';
import { events } from './events';
import isSupportedPage from './isSupportedPage';
import { isMac } from './platform';
import { isMac, isWindows } from './platform';
import store from './store';

interface WindowProps {
Expand Down Expand Up @@ -76,15 +76,6 @@ function isInBounds(rect: Rectangle) {
});
}

async function getLastSeenBackgroundColor(
window: BrowserWindow,
): Promise<string> {
// We're capturing the background color to use as main browser window background color.
return window.webContents.executeJavaScript(
`getComputedStyle(document.body).getPropertyValue('--background-root');`,
);
}

function updateStoreWithFocusedWindowValues() {
const windows = BrowserWindow.getAllWindows();

Expand All @@ -97,15 +88,43 @@ function updateStoreWithFocusedWindowValues() {
const window = BrowserWindow.getFocusedWindow() || windows[0];

store.setWindowBounds(window.getBounds());
}

getLastSeenBackgroundColor(window).then((backgroundColor) => {
store.setLastSeenBackgroundColor(backgroundColor);
});
function getPlatformSpecificStyling({
backgroundColor,
foregroundColor,
}: {
backgroundColor: string;
foregroundColor: string;
}): Partial<BrowserWindowConstructorOptions> {
// For MacOS and Windows we use a hidden titlebar and move the OS window buttons into the header of the interface
// the corresponding CSS adjustments to enable this live in the repl-it-web repo.
if (isMac()) {
return {
titleBarStyle: 'hidden',
titleBarOverlay: { height: 48 },
trafficLightPosition: { x: 20, y: 16 },
};
}

if (isWindows()) {
return {
titleBarStyle: 'hidden',
titleBarOverlay: {
color: backgroundColor,
symbolColor: foregroundColor,
height: 47, // leaving 1px for border on the top of the pane
sergeichestakov marked this conversation as resolved.
Show resolved Hide resolved
},
};
}

return {};
}

export function createWindow(props?: WindowProps): BrowserWindow {
updateStoreWithFocusedWindowValues();
const backgroundColor = store.getLastSeenBackgroundColor();
const foregroundColor = store.getLastSeenForegroundColor();
const url = createURL(props?.url);
let lastOpenRepl = store.getLastOpenRepl();
const disposeOnLastOpenReplChange = store.onLastOpenReplChange((newValue) => {
Expand All @@ -114,19 +133,10 @@ export function createWindow(props?: WindowProps): BrowserWindow {

log.info('Creating window with URL: ', url);

// 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: 48,
},
trafficLightPosition: { x: 20, y: 16 },
}
: {};
const platformStyling = getPlatformSpecificStyling({
foregroundColor,
backgroundColor,
});

const window = new BrowserWindow({
webPreferences: {
Expand Down Expand Up @@ -189,9 +199,7 @@ export function createWindow(props?: WindowProps): BrowserWindow {

window.setBounds(store.getWindowBounds());

window.on('close', async () => {
const bgColor = await getLastSeenBackgroundColor(window);
store.setLastSeenBackgroundColor(bgColor);
window.on('close', () => {
store.setWindowBounds(window.getBounds());
disposeOnLastOpenReplChange();
});
Expand Down
1 change: 1 addition & 0 deletions src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export enum events {
CHECK_FOR_UPDATES = 'CHECK_FOR_UPDATES',
ON_ENTER_FULLSCREEN = 'ON_ENTER_FULLSCREEN',
ON_LEAVE_FULLSCREEN = 'ON_LEAVE_FULLSCREEN',
THEME_VALUES_CHANGED = 'THEME_VALUES_CHANGED',
}
25 changes: 25 additions & 0 deletions src/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { events } from './events';
import { isLinux } from './platform';
import store from './store';
import isSupportedPage from './isSupportedPage';
import { isWindows } from './platform';

function logEvent(event: events, params?: Record<string, unknown>) {
log.info(
Expand Down Expand Up @@ -77,4 +78,28 @@ export function setIpcEventListeners(): void {

return response;
});

ipcMain.on(events.THEME_VALUES_CHANGED, (event, themeValues) => {
logEvent(events.THEME_VALUES_CHANGED, themeValues);

const senderWindow = BrowserWindow.getAllWindows().find(
(win) => win.webContents.id === event.sender.id,
);

const { backgroundRoot, foregroundDefault } = themeValues;

// Update store values
store.setLastSeenBackgroundColor(backgroundRoot);
store.setLastSeenForegroundColor(foregroundDefault);

// Update window styling
senderWindow.setBackgroundColor(backgroundRoot);

if (isWindows()) {
senderWindow.setTitleBarOverlay({
color: backgroundRoot,
symbolColor: foregroundDefault,
});
}
});
}
7 changes: 5 additions & 2 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ const platform = parseArgument('platform');

contextBridge.exposeInMainWorld('replitDesktop', {
closeCurrentWindow: () => ipcRenderer.send(events.CLOSE_CURRENT_WINDOW),
openWindow: (replSlug: string) =>
ipcRenderer.send(events.OPEN_WINDOW, replSlug),
openWindow: (path: string) => ipcRenderer.send(events.OPEN_WINDOW, path),
openExternalUrl: (url: string) =>
ipcRenderer.send(events.OPEN_EXTERNAL_URL, url),
onAuthTokenReceived: (callback: (token: string) => void) => {
Expand All @@ -48,6 +47,10 @@ contextBridge.exposeInMainWorld('replitDesktop', {
ipcRenderer.invoke(events.SHOW_MESSAGE_BOX, params),
onEnterFullscreen: makeEventHandler(events.ON_ENTER_FULLSCREEN),
onLeaveFullscreen: makeEventHandler(events.ON_LEAVE_FULLSCREEN),
updateThemeValues: (themeValues: {
backgroundRoot: string;
foregroundDefault: string;
}) => ipcRenderer.send(events.THEME_VALUES_CHANGED, themeValues),
checkForUpdates: () => ipcRenderer.send(events.CHECK_FOR_UPDATES),
logout: () => ipcRenderer.send(events.LOGOUT),
platform,
Expand Down
13 changes: 12 additions & 1 deletion src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import Store from 'electron-store';

const keys = {
LAST_SEEN_BACKGROUND_COLOR: 'LAST_SEEN_BACKGROUND_COLOR',
LAST_SEEN_FOREGROUND_COLOR: 'LAST_SEEN_FOREGROUND_COLOR',
LAST_OPEN_REPL: 'LAST_OPEN_REPL',
WINDOW_BOUNDS: 'WINDOW_BOUNDS',
NUM_DISPLAYS: 'NUM_DISPLAYS',
};

// var(--background-root) value for dark mode
// Default values for var(--background-root) and var(--foreground-default) in dark mode.
const defaultBgColor = '#0E1525';
const defaultFgColor = '#F5F9FC';

function createStore() {
const store = new Store();
Expand All @@ -24,6 +26,15 @@ function createStore() {
defaultBgColor,
) as string;
},
setLastSeenForegroundColor(color: string) {
store.set(keys.LAST_SEEN_FOREGROUND_COLOR, color);
},
getLastSeenForegroundColor(): string {
return store.get(
keys.LAST_SEEN_FOREGROUND_COLOR,
defaultFgColor,
) as string;
},
clearWindowBounds() {
store.delete(keys.WINDOW_BOUNDS);
},
Expand Down