├── .gitignore ├── icons ├── gcal-icon.png ├── gcal-icon.icns └── gcal-large.png ├── package-config └── linux.json ├── README.md ├── package.json └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /icons/gcal-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markstuart/electron-gcal/HEAD/icons/gcal-icon.png -------------------------------------------------------------------------------- /icons/gcal-icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markstuart/electron-gcal/HEAD/icons/gcal-icon.icns -------------------------------------------------------------------------------- /icons/gcal-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markstuart/electron-gcal/HEAD/icons/gcal-large.png -------------------------------------------------------------------------------- /package-config/linux.json: -------------------------------------------------------------------------------- 1 | { 2 | "dest": "dist/installers/", 3 | "src": "dist/GCal-linux-x64/", 4 | "bin": "GCal", 5 | "arch": "amd64", 6 | "icon": "icons/gcal-icon.png", 7 | "categories": [ 8 | "Office", 9 | "Calendar" 10 | ] 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Electron GCal 2 | 3 | Unable to find a decent calendar app? Sick of keeping that Google Calendar tab open in your browser? 4 | 5 | Then this is for you. 6 | 7 | It's a super simple Electron wrapper around the Google Calendar site. All links in the page (e.g. in calendar event information) will open in 8 | your default browser. 9 | 10 | ## Releases 11 | 12 | Go to the [releases](https://github.com/markstuart/electron-gcal/releases) page to download the installer for your operating system. 13 | 14 | **Caveat**: at this time, only Linux .deb and MacOS .dmg installers are provided. 15 | 16 | ## Development 17 | 18 | Clone the repo and run `npm install`. 19 | 20 | `npm start` should get the app running on any operating system. 21 | 22 | ## Issues 23 | 24 | Please feel free to raise an issue here, or a pull request if you have something you'd like to contribute. 25 | 26 | All contributions are welcome :) 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-gcal", 3 | "version": "0.0.3", 4 | "productName": "GCal", 5 | "description": "Google Calendar desktop app", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "electron .", 9 | "build:linux": "electron-packager . --platform linux --arch x64 --icon icons/gcal-icon.png --out dist/ --overwrite", 10 | "build:osx": "electron-packager . --platform darwin --arch x64 --icon icons/gcal-icon.icns --out dist/ --overwrite", 11 | "deb": "electron-installer-debian --config package-config/linux.json", 12 | "dmg": "electron-installer-dmg ./dist/GCal-darwin-x64/GCal.app GCal --icon icons/gcal-icon.icns --out dist/installers", 13 | "package:deb": "npm run build:linux && npm run deb", 14 | "package:dmg": "npm run build:osx && npm run dmg" 15 | }, 16 | "keywords": [ 17 | "electron", 18 | "calendar" 19 | ], 20 | "author": "Mark Stuart", 21 | "license": "ISC", 22 | "devDependencies": { 23 | "electron": "^11.5.0", 24 | "electron-installer-debian": "^3.0.0", 25 | "electron-installer-dmg": "^3.0.0", 26 | "electron-packager": "^14.2.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow, shell } = require('electron') 2 | const path = require('path') 3 | 4 | app.name = 'GCal' 5 | 6 | const handleLinkClicks = (webContents) => { 7 | /** 8 | * First, we set up a dom handler that captures the click 9 | * on the way in, rather than out (see 'true' as last arg). 10 | * Then, if the target is an a tag we call window.open with 11 | * the href and prevent the other handlers that electron adds 12 | * from running. window.open triggers the 'new-window' event 13 | * on the webContents, and we tell the OS to use the default 14 | * browser to open the link. 15 | */ 16 | webContents.on('dom-ready', () => { 17 | const script = ` 18 | document.addEventListener('click', event => { 19 | if (event.target.tagName === 'A') { 20 | event.preventDefault(); 21 | window.open(event.target.href); 22 | } 23 | }, true); 24 | ` 25 | webContents.executeJavaScript(script, false) 26 | }) 27 | 28 | webContents.on('new-window', (event, url) => { 29 | event.preventDefault() 30 | if (url && url !== 'about:blank') { 31 | shell.openExternal(url) 32 | } 33 | }) 34 | } 35 | 36 | const createWindow = () => { 37 | // Create the browser window. 38 | const win = new BrowserWindow({ 39 | width: 1280, 40 | height: 720, 41 | title: 'Google Calendar', 42 | titleBarStyle: 'hidden', 43 | icon: path.join(__dirname, 'icons/gcal-icon.png'), 44 | backgroundColor: '#fff', 45 | }) 46 | 47 | // and load the index.html of the app. 48 | win.loadURL('https://calendar.google.com/calendar/r/week') 49 | 50 | handleLinkClicks(win.webContents) 51 | } 52 | 53 | // This method will be called when Electron has finished 54 | // initialization and is ready to create browser windows. 55 | // Some APIs can only be used after this event occurs. 56 | app.whenReady().then(createWindow) 57 | app.allowRendererProcessReuse = true 58 | 59 | // Quit when all windows are closed. 60 | app.on('window-all-closed', () => { 61 | // On macOS it is common for applications and their menu bar 62 | // to stay active until the user quits explicitly with Cmd + Q 63 | if (process.platform !== 'darwin') { 64 | app.quit() 65 | } 66 | }) 67 | 68 | app.on('activate', () => { 69 | // On macOS it's common to re-create a window in the app when the 70 | // dock icon is clicked and there are no other windows open. 71 | if (BrowserWindow.getAllWindows().length === 0) { 72 | createWindow() 73 | } 74 | }) 75 | 76 | // In this file you can include the rest of your app's specific main process 77 | // code. You can also put them in separate files and require them here. 78 | --------------------------------------------------------------------------------