mirror of
https://github.com/scratchfoundation/scratch-desktop.git
synced 2024-12-23 14:12:27 -05:00
commit
8dcbbfe5c9
4 changed files with 106 additions and 19 deletions
|
@ -1,4 +1,4 @@
|
||||||
import {BrowserWindow, Menu, app, dialog} from 'electron';
|
import {BrowserWindow, Menu, app, dialog, ipcMain} from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {format as formatUrl} from 'url';
|
import {format as formatUrl} from 'url';
|
||||||
import {getFilterForExtension} from './FileFilters';
|
import {getFilterForExtension} from './FileFilters';
|
||||||
|
@ -13,20 +13,17 @@ const defaultSize = {width: 1280, height: 800}; // good for MAS screenshots
|
||||||
|
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
const createMainWindow = () => {
|
// global window references prevent them from being garbage-collected
|
||||||
|
const _windows = {};
|
||||||
|
|
||||||
|
const createWindow = ({url, ...browserWindowOptions}) => {
|
||||||
const window = new BrowserWindow({
|
const window = new BrowserWindow({
|
||||||
width: defaultSize.width,
|
|
||||||
height: defaultSize.height,
|
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
show: false
|
show: false,
|
||||||
|
...browserWindowOptions
|
||||||
});
|
});
|
||||||
const webContents = window.webContents;
|
const webContents = window.webContents;
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
const osxMenu = Menu.buildFromTemplate(MacOSMenu(app));
|
|
||||||
Menu.setApplicationMenu(osxMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDevelopment) {
|
if (isDevelopment) {
|
||||||
webContents.openDevTools();
|
webContents.openDevTools();
|
||||||
import('electron-devtools-installer').then(importedModule => {
|
import('electron-devtools-installer').then(importedModule => {
|
||||||
|
@ -46,15 +43,38 @@ const createMainWindow = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isDevelopment) {
|
if (isDevelopment) {
|
||||||
window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`);
|
window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}/${url}`);
|
||||||
} else {
|
} else {
|
||||||
window.loadURL(formatUrl({
|
window.loadURL(formatUrl({
|
||||||
pathname: path.join(__dirname, 'index.html'),
|
pathname: path.join(__dirname, url),
|
||||||
protocol: 'file',
|
protocol: 'file',
|
||||||
slashes: true
|
slashes: true
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAboutWindow = () => {
|
||||||
|
const window = createWindow({
|
||||||
|
width: 400,
|
||||||
|
height: 400,
|
||||||
|
parent: _windows.main,
|
||||||
|
title: 'About Scratch Desktop',
|
||||||
|
url: 'index.html?route=about'
|
||||||
|
});
|
||||||
|
return window;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createMainWindow = () => {
|
||||||
|
const window = createWindow({
|
||||||
|
width: defaultSize.width,
|
||||||
|
height: defaultSize.height,
|
||||||
|
title: 'Scratch Desktop',
|
||||||
|
url: 'index.html'
|
||||||
|
});
|
||||||
|
const webContents = window.webContents;
|
||||||
|
|
||||||
webContents.session.on('will-download', (ev, item) => {
|
webContents.session.on('will-download', (ev, item) => {
|
||||||
const itemPath = item.getFilename();
|
const itemPath = item.getFilename();
|
||||||
const baseName = path.basename(itemPath);
|
const baseName = path.basename(itemPath);
|
||||||
|
@ -104,6 +124,11 @@ const createMainWindow = () => {
|
||||||
return window;
|
return window;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
const osxMenu = Menu.buildFromTemplate(MacOSMenu(app));
|
||||||
|
Menu.setApplicationMenu(osxMenu);
|
||||||
|
}
|
||||||
|
|
||||||
// quit application when all windows are closed
|
// quit application when all windows are closed
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
app.quit();
|
app.quit();
|
||||||
|
@ -113,13 +138,19 @@ app.on('will-quit', () => {
|
||||||
telemetry.appWillClose();
|
telemetry.appWillClose();
|
||||||
});
|
});
|
||||||
|
|
||||||
// global reference to mainWindow (necessary to prevent window from being garbage collected)
|
|
||||||
let _mainWindow;
|
|
||||||
|
|
||||||
// create main BrowserWindow when electron is ready
|
// create main BrowserWindow when electron is ready
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
_mainWindow = createMainWindow();
|
_windows.main = createMainWindow();
|
||||||
_mainWindow.on('closed', () => {
|
_windows.main.on('closed', () => {
|
||||||
_mainWindow = null;
|
delete _windows.main;
|
||||||
|
});
|
||||||
|
_windows.about = createAboutWindow();
|
||||||
|
_windows.about.on('close', event => {
|
||||||
|
event.preventDefault();
|
||||||
|
_windows.about.hide();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on('open-about-window', () => {
|
||||||
|
_windows.about.show();
|
||||||
|
});
|
||||||
|
|
43
src/renderer/about.jsx
Normal file
43
src/renderer/about.jsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import {author, productName, version} from '../../package.json';
|
||||||
|
|
||||||
|
import logo from '../icon/ScratchDesktop.svg';
|
||||||
|
|
||||||
|
// TODO: localization?
|
||||||
|
const AboutElement = () => (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: 'white',
|
||||||
|
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif',
|
||||||
|
fontWeight: 'bolder',
|
||||||
|
margin: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div><img
|
||||||
|
alt={`${productName} icon`}
|
||||||
|
src={logo}
|
||||||
|
style={{
|
||||||
|
maxWidth: '10rem',
|
||||||
|
maxHeight: '10rem'
|
||||||
|
}}
|
||||||
|
/></div>
|
||||||
|
<h2>{productName}</h2>
|
||||||
|
<div>Version {version}</div>
|
||||||
|
<table style={{fontSize: 'x-small'}}>
|
||||||
|
{
|
||||||
|
['Electron', 'Chrome'].map(component => {
|
||||||
|
const componentVersion = process.versions[component.toLowerCase()];
|
||||||
|
return <tr key={component}><td>{component}</td><td>{componentVersion}</td></tr>;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const appTarget = document.getElementById('app');
|
||||||
|
ReactDOM.render(<AboutElement />, appTarget);
|
|
@ -45,6 +45,9 @@ const ScratchDesktopHOC = function (WrappedComponent) {
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
ipcRenderer.removeListener('setTitleFromSave', this.handleSetTitleFromSave);
|
ipcRenderer.removeListener('setTitleFromSave', this.handleSetTitleFromSave);
|
||||||
}
|
}
|
||||||
|
handleClickLogo () {
|
||||||
|
ipcRenderer.send('open-about-window');
|
||||||
|
}
|
||||||
handleProjectTelemetryEvent (event, metadata) {
|
handleProjectTelemetryEvent (event, metadata) {
|
||||||
ipcRenderer.send(event, metadata);
|
ipcRenderer.send(event, metadata);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +69,7 @@ const ScratchDesktopHOC = function (WrappedComponent) {
|
||||||
isScratchDesktop
|
isScratchDesktop
|
||||||
projectId={defaultProjectId}
|
projectId={defaultProjectId}
|
||||||
showTelemetryModal={shouldShowTelemetryModal}
|
showTelemetryModal={shouldShowTelemetryModal}
|
||||||
|
onClickLogo={this.handleClickLogo}
|
||||||
onProjectTelemetryEvent={this.handleProjectTelemetryEvent}
|
onProjectTelemetryEvent={this.handleProjectTelemetryEvent}
|
||||||
onStorageInit={this.handleStorageInit}
|
onStorageInit={this.handleStorageInit}
|
||||||
onTelemetryModalOptIn={this.handleTelemetryModalOptIn}
|
onTelemetryModalOptIn={this.handleTelemetryModalOptIn}
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
// this is an async import so that it doesn't block the first render
|
// this is an async import so that it doesn't block the first render
|
||||||
// index.html contains a loading/splash screen which will display while this import loads
|
// index.html contains a loading/splash screen which will display while this import loads
|
||||||
import('./app.jsx');
|
|
||||||
|
const route = new URLSearchParams(window.location.search).get('route') || 'app';
|
||||||
|
switch (route) {
|
||||||
|
case 'app':
|
||||||
|
import('./app.jsx');
|
||||||
|
break;
|
||||||
|
case 'about':
|
||||||
|
import('./about.jsx');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue