diff --git a/README.md b/README.md index 4020832..e1da45c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,11 @@ A mob programming timer, inspired by the [MobProgramming/MobTimer.Python](https: Learn all about mobbing at the above github page, and at [mobprogramming.org](http://mobprogramming.org/). This app was created to have an easier to maintain cross-platform application (using github's [electron](electron.atom.io) framework). +## Contributors +A big thanks to [ehei](https://github.com/ehei) for figuring out the +autoUpdater (which I couldn't for the life of me get to work)! +## Contributing To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line: ```bash @@ -14,8 +18,6 @@ git clone https://github.com/dillonkearns/mobster cd mobster # Install dependencies npm install -# Run the test watcher -npm test # Run the app npm start ``` diff --git a/main.js b/main.js index f815144..d5144c7 100644 --- a/main.js +++ b/main.js @@ -1,5 +1,6 @@ const electron = require('electron') -const {ipcMain, globalShortcut, app, Tray, BrowserWindow, dialog, autoUpdater} = require('electron') +const {ipcMain, globalShortcut, app, Tray, BrowserWindow, dialog} = require('electron') +const autoUpdater = require('electron-updater').autoUpdater const path = require('path') const url = require('url') @@ -18,6 +19,7 @@ const timerHeight = 130 const timerWidth = 150 const onMac = /^darwin/.test(process.platform) +const isDev = require('electron-is-dev') function positionWindowLeft(window) { let {width, height} = electron.screen.getPrimaryDisplay().workAreaSize @@ -77,12 +79,9 @@ function createWindow () { icon: `${assetsDirectory}/icon.ico` }) mainWindow.maximize() - mainWindow.setResizable(false) electron.screen.on('display-metrics-changed', function () { - mainWindow.setResizable(true) mainWindow.maximize() - mainWindow.setResizable(false) }) mainWindow.loadURL(url.format({ @@ -91,8 +90,6 @@ function createWindow () { slashes: true })) - mainWindow.center() - ipcMain.on('start-timer', (event, flags) => { startTimer(flags) mainWindow.hide() @@ -108,6 +105,10 @@ function createWindow () { app.quit() }) + ipcMain.on('quit-and-install', () => { + autoUpdater.quitAndInstall() + }) + // Emitted when the window is closed. mainWindow.on('closed', function () { // Dereference the window object, usually you would store windows @@ -144,62 +145,19 @@ const createTray = () => { tray.on('click', onClickTrayIcon) } -function showDialog(message) { - dialog.showMessageBox({ - type: 'info', - message: message - }) -} - -function createWindows() { +function onReady() { createWindow() createTray() - globalShortcut.register('CommandOrControl+Shift+K', () => { - if (timerWindow) { - let dialogActionIndex = dialog.showMessageBox({ - type: 'warning', - buttons: ['Stop timer', 'Keep it running'], - message: 'Stop the timer?', - cancelId: 1, - }) - if (dialogActionIndex !== 1) { - closeTimer() - showSetupAgain(mainWindow) - } - } else { - toggleMainWindow() - } - }) - globalShortcut.register('CommandOrControl+Shift+;', () => { - copyActiveMobsters() - }) - autoUpdater.logger = log; - autoUpdater.on('checking-for-update', () => { - showDialog('checking-for-update') - }); - - autoUpdater.on('update-available', () => { - showDialog('update-available') - }); - - autoUpdater.on('update-downloaded', () => { - showDialog('update-downloaded') - }); - - autoUpdater.on('update-not-available', () => { - showDialog('update-not-available') - }); - showDialog('about to search for updates') - autoUpdater.checkForUpdates() -} -function copyActiveMobsters() { - mainWindow.webContents.send('copy-active-mobsters') + registerShortcuts() + if (!onMac && !isDev) { // don't run autoUpdater on mac until the app is signed + setupAutoUpdater() + } } // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. -app.on('ready', createWindows) +app.on('ready', onReady) // Quit when all windows are closed. app.on('window-all-closed', function () { @@ -218,5 +176,48 @@ app.on('activate', function () { } }) -// In this file you can include the rest of your app's specific main process -// code. You can also put them in separate files and require them here. +function setupAutoUpdater() { + autoUpdater.logger = log; + autoUpdater.on('checking-for-update', () => { + log.info('checking-for-update') + }); + + autoUpdater.on('update-available', () => { + log.info('update-available') + }); + + autoUpdater.on('update-downloaded', (versionInfo) => { + log.info('update-downloaded... Imma let you finish... but first, Imma install it once you push okay ;-)') + log.info('update-available: ', versionInfo) + mainWindow.webContents.send('update-downloaded', versionInfo) + }); + + autoUpdater.on('update-not-available', () => { + log.info('update-not-available') + }); + autoUpdater.checkForUpdates() +} + +function registerShortcuts() { + globalShortcut.register('CommandOrControl+Shift+K', () => { + if (timerWindow) { + let dialogActionIndex = dialog.showMessageBox({ + type: 'warning', + buttons: ['Stop timer', 'Keep it running'], + message: 'Stop the timer?', + cancelId: 1, + }) + if (dialogActionIndex !== 1) { + closeTimer() + showSetupAgain(mainWindow) + } + } else { + toggleMainWindow() + } + }) + globalShortcut.register('CommandOrControl+Shift+;', copyActiveMobsters) +} + +function copyActiveMobsters() { + mainWindow.webContents.send('copy-active-mobsters') +} diff --git a/package.json b/package.json index 75c0934..dbf7141 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Mobster", - "version": "0.0.4", + "version": "0.0.6", "description": "A cross-platform mob programming timer built on web technologies", "main": "main.js", "scripts": { @@ -35,12 +35,14 @@ "devDependencies": { "electron": "^1.5.0", "electron-builder": "^11.7.0", + "elm": "^0.18.0", "elm-css": "^0.6.0", "elm-test": "^0.18.2" }, "dependencies": { "electron-is-dev": "^0.1.2", "electron-log": "^1.3.0", + "electron-updater": "^1.6.0", "jquery": "^3.1.1" } } diff --git a/setup.html b/setup.html index 95b7b5c..0c2dcc9 100644 --- a/setup.html +++ b/setup.html @@ -125,6 +125,10 @@ document.getElementById(id).select() }) + setup.ports.quitAndInstall.subscribe(function() { + ipcRenderer.send('quit-and-install') + }) + setup.ports.copyActiveMobsters.subscribe(function(activeMobsters) { clipboard.writeText(activeMobsters) }) @@ -133,6 +137,11 @@ window.localStorage.setItem('setup', JSON.stringify(setup)) }) + ipcRenderer.on('update-downloaded', function (event, updatedVersion) { + console.log('on update-downloaded. updatedVersion = ', updatedVersion) + setup.ports.updateDownloaded.send("Not a real version...") + }) + ipcRenderer.on('timer-done', function (event, elapsedSeconds) { setup.ports.timeElapsed.send(elapsedSeconds) }) diff --git a/src/Setup/Main.elm b/src/Setup/Main.elm index d568073..d0e8d4e 100644 --- a/src/Setup/Main.elm +++ b/src/Setup/Main.elm @@ -43,9 +43,11 @@ type Msg | UpdateExperimentInput String | EnterRating Int | Quit + | QuitAndInstall | ComboMsg Keyboard.Combo.Msg | ShuffleMobsters | TimeElapsed Int + | UpdateAvailable String | CopyActiveMobsters () | ResetBreakData @@ -78,6 +80,7 @@ type alias Model = , secondsSinceBreak : Int , intervalsSinceBreak : Int , intervalsPerBreak : Int + , availableUpdateVersion : Maybe String } @@ -100,6 +103,7 @@ initialModel = , secondsSinceBreak = 0 , intervalsSinceBreak = 0 , intervalsPerBreak = 6 + , availableUpdateVersion = Nothing } @@ -128,6 +132,9 @@ port saveSetup : Mobster.MobsterData -> Cmd msg port quit : () -> Cmd msg +port quitAndInstall : () -> Cmd msg + + port selectDuration : String -> Cmd msg @@ -137,6 +144,9 @@ port copyActiveMobsters : String -> Cmd msg port timeElapsed : (Int -> msg) -> Sub msg +port updateDownloaded : (String -> msg) -> Sub msg + + port onCopyMobstersShortcut : (() -> msg) -> Sub msg @@ -465,14 +475,33 @@ reorderButtonView mobster = ] +updateAvailableView : Maybe String -> Html Msg +updateAvailableView availableUpdateVersion = + case availableUpdateVersion of + Nothing -> + div [] [] + + Just version -> + div [ Attr.class "alert alert-success" ] + [ span [ Attr.class "glyphicon glyphicon-flag", class [ BufferRight ] ] [] + , text ("A new version is downloaded and ready to install. ") + , a [ onClick QuitAndInstall, Attr.href "#", Attr.class "alert-link" ] [ text "Update now" ] + , text "." + ] + + view : Model -> Html Msg view model = - case model.screenState of - Configure -> - configureView model + let + mainView = + case model.screenState of + Configure -> + configureView model - Continue -> - continueView model + Continue -> + continueView model + in + div [] [ updateAvailableView model.availableUpdateVersion, mainView ] resetBreakData : Model -> Model @@ -588,6 +617,12 @@ update msg model = ResetBreakData -> (model |> resetBreakData) ! [] + UpdateAvailable availableUpdateVersion -> + { model | availableUpdateVersion = Just availableUpdateVersion } ! [] + + QuitAndInstall -> + model ! [ quitAndInstall () ] + reorderOperation : List String -> Msg reorderOperation shuffledMobsters = @@ -646,6 +681,7 @@ subscriptions model = Sub.batch [ Keyboard.Combo.subscriptions model.combos , timeElapsed TimeElapsed + , updateDownloaded UpdateAvailable , onCopyMobstersShortcut CopyActiveMobsters ]