diff --git a/app/main/auto-updater/config.js b/app/main/auto-updater/config.js deleted file mode 100644 index 6d40acadf..000000000 --- a/app/main/auto-updater/config.js +++ /dev/null @@ -1,9 +0,0 @@ -const baseFeedUrl = `https://appium-inspector-hazel.vercel.app`; - -export function getFeedUrl(version) { - let platform = process.platform; - if (platform.toLowerCase() === 'linux') { - platform = 'AppImage'; - } - return `${baseFeedUrl}/update/${platform}/${version}`; -} diff --git a/app/main/auto-updater/index.js b/app/main/auto-updater/index.js deleted file mode 100644 index ef74e537c..000000000 --- a/app/main/auto-updater/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Auto Updater - * - * Similar to https://electronjs.org/docs/api/auto-updater#events - * See https://electronjs.org/docs/tutorial/updates for documentation - */ -import B from 'bluebird'; -import {app, autoUpdater, dialog} from 'electron'; -import _ from 'lodash'; -import moment from 'moment'; - -import i18n from '../../configs/i18next.config'; -import env from '../../env'; -import {setUpAutoUpdater} from './update-checker'; - -const isDev = process.env.NODE_ENV === 'development'; -const runningLocally = isDev || process.env.RUNNING_LOCALLY; - -let checkNewUpdates = _.noop; - -if (!runningLocally && !process.env.RUNNING_IN_SPECTRON) { - // put autoupdater in try block so that it doesn't break if autoupdater doesn't work - try { - checkNewUpdates = setUpAutoUpdater({ - autoUpdater, - app, - moment, - i18n, - env, - dialog, - B, - }); - } catch (e) {} -} - -export {checkNewUpdates}; diff --git a/app/main/auto-updater/update-checker.js b/app/main/auto-updater/update-checker.js deleted file mode 100644 index dceb3c7a2..000000000 --- a/app/main/auto-updater/update-checker.js +++ /dev/null @@ -1,126 +0,0 @@ -import axios from 'axios'; -import semver from 'semver'; - -import {getFeedUrl} from './config'; - -export async function checkUpdate(currentVersion) { - try { - // The response is like (macOS): - // { "name":"v1.15.0-1", - // "notes":"* Bump up Appium to v1.15.0", - // "pub_date":"2019-10-04T04:40:37Z", - // "url":"https://github.com/appium/appium-desktop/releases/download/v1.15.0-1/Appium-1.15.0-1-mac.zip"} - const res = await axios.get(getFeedUrl(currentVersion)); - if (res && semver.lt(currentVersion, res.name)) { - return res; - } - } catch (ign) {} - - return false; -} - -export function setUpAutoUpdater({autoUpdater, app, moment, i18n, env, dialog, B}) { - autoUpdater.setFeedURL(getFeedUrl(app.getVersion())); - - /** - * Check for new updates - */ - const checkNewUpdates = async function (fromMenu) { - // autoupdate.checkForUpdates always downloads updates immediately - // This method (getUpdate) let's us take a peek to see if there is an update - // available before calling .checkForUpdates - if (process.env.RUNNING_IN_SPECTRON) { - return; - } - const update = await checkUpdate(app.getVersion()); - if (update) { - let {name, notes, pub_date: pubDate} = update; - pubDate = moment(pubDate).format(i18n.t('datetimeFormat')); - - let detail = i18n.t('updateDetails', {pubDate, notes: notes.replace('*', '\n*')}); - if (env.NO_AUTO_UPDATE) { - detail += `\n\nhttps://www.github.com/appium/appium-inspector/releases/latest`; - } - - // Ask user if they wish to install now or later - if (!process.env.RUNNING_IN_SPECTRON) { - dialog.showMessageBox( - { - type: 'info', - buttons: env.NO_AUTO_UPDATE - ? [i18n.t('OK')] - : [i18n.t('Install Now'), i18n.t('Install Later')], - message: i18n.t('appiumIsAvailable', {name}), - detail, - }, - (response) => { - if (response === 0) { - // If they say yes, get the updates now - if (!env.NO_AUTO_UPDATE) { - autoUpdater.checkForUpdates(); - } - } - }, - ); - } - } else { - if (fromMenu) { - autoUpdater.emit('update-not-available'); - } else { - // If no updates found check for updates every hour - await B.delay(60 * 60 * 1000); - checkNewUpdates(); - } - } - }; - - // Inform user when the download is starting and that they'll be notified again when it is complete - autoUpdater.on('update-available', () => { - dialog.showMessageBox({ - type: 'info', - buttons: [i18n.t('OK')], - message: i18n.t('Update Download Started'), - detail: i18n.t('updateIsBeingDownloaded'), - }); - }); - - // Handle the unusual case where we checked the updates endpoint, found an update - // but then after calling 'checkForUpdates', nothing was there - autoUpdater.on('update-not-available', () => { - dialog.showMessageBox({ - type: 'info', - buttons: [i18n.t('OK')], - message: i18n.t('No update available'), - detail: i18n.t('Appium Inspector is up-to-date'), - }); - }); - - // When it's done, ask if user want to restart now or later - autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => { - dialog.showMessageBox( - { - type: 'info', - buttons: [i18n.t('Restart Now'), i18n.t('Later')], - message: i18n.t('Update Downloaded'), - detail: i18n.t('updateIsDownloaded', {releaseName}), - }, - (response) => { - // If they say yes, restart now - if (response === 0) { - autoUpdater.quitAndInstall(); - } - }, - ); - }); - - // Handle error case - autoUpdater.on('error', (message) => { - dialog.showMessageBox({ - type: 'error', - message: i18n.t('Could not download update'), - detail: i18n.t('updateDownloadFailed', {message}), - }); - }); - - return checkNewUpdates; -} diff --git a/app/main/helpers.js b/app/main/helpers.js index 6d37417a5..b91bdfeb7 100644 --- a/app/main/helpers.js +++ b/app/main/helpers.js @@ -1,3 +1,5 @@ +import i18n from '../configs/i18next.config'; + const APPIUM_SESSION_FILE_VERSION = '1.0'; export function getAppiumSessionFilePath(argv, isPackaged, isDev) { @@ -26,4 +28,6 @@ export function getSaveableState(reduxState) { }; } +export const t = (string, params = null) => i18n.t(string, params); + export const APPIUM_SESSION_EXTENSION = 'appiumsession'; diff --git a/app/main/menus.js b/app/main/menus.js index e4a58e009..adc1f8485 100644 --- a/app/main/menus.js +++ b/app/main/menus.js @@ -2,8 +2,8 @@ import {Menu, app, dialog, shell} from 'electron'; import {languageList} from '../configs/app.config'; import i18n from '../configs/i18next.config'; -import {checkNewUpdates} from './auto-updater'; -import {APPIUM_SESSION_EXTENSION} from './helpers'; +import {checkForUpdates} from './updater'; +import {APPIUM_SESSION_EXTENSION, t} from './helpers'; import {launchNewSessionWindow} from './windows'; const INSPECTOR_DOCS_URL = 'https://appium.github.io/appium-inspector'; @@ -12,8 +12,6 @@ const APPIUM_FORUM_URL = 'https://discuss.appium.io'; const GITHUB_ISSUES_URL = 'https://github.com/appium/appium-inspector/issues'; const CROWDIN_URL = 'https://crowdin.com/project/appium-desktop'; -const t = (string, params = null) => i18n.t(string, params); - const separator = {type: 'separator'}; function showAppInfoPopup() { @@ -40,7 +38,7 @@ async function openFile(mainWindow) { async function saveAs(mainWindow) { const {canceled, filePath} = await dialog.showSaveDialog({ - title: i18n.t('saveAs'), + title: t('saveAs'), filters: [{name: 'Appium', extensions: [APPIUM_SESSION_EXTENSION]}], }); if (!canceled) { @@ -67,7 +65,7 @@ function optionAbout() { function optionCheckForUpdates() { return { label: t('Check for Updates…'), - click: () => checkNewUpdates(true), + click: () => checkForUpdates(), }; } diff --git a/app/main/updater.js b/app/main/updater.js new file mode 100644 index 000000000..779dddf3b --- /dev/null +++ b/app/main/updater.js @@ -0,0 +1,57 @@ +import {dialog} from 'electron'; +import {autoUpdater} from 'electron-updater'; + +import {t} from './helpers'; + +const RELEASES_LINK = 'https://github.com/appium/appium-inspector/releases'; + +autoUpdater.autoDownload = false; +autoUpdater.autoInstallOnAppQuit = false; + +autoUpdater.on('error', (error) => { + dialog.showErrorBox(t('Could not download update'), t('updateDownloadFailed', {message: error})); +}); + +autoUpdater.on('update-not-available', () => { + dialog.showMessageBox({ + type: 'info', + buttons: [t('OK')], + message: t('No update available'), + detail: t('Appium Inspector is up-to-date'), + }); +}); + +autoUpdater.on('update-available', async ({version, releaseDate}) => { + const pubDate = new Date(releaseDate).toDateString(); + const {response} = await dialog.showMessageBox({ + type: 'info', + message: t('appiumIsAvailable', {name: version}), + buttons: [t('Install Now'), t('Install Later')], + detail: t('updateDetails', {pubDate, notes: RELEASES_LINK}), + }); + if (response === 0) { + // download is started without waiting for the dialog box to be dismissed + dialog.showMessageBox({ + type: 'info', + buttons: [t('OK')], + message: t('updateIsBeingDownloaded'), + }); + autoUpdater.downloadUpdate(); + } +}); + +autoUpdater.on('update-downloaded', async ({releaseName}) => { + const {response} = await dialog.showMessageBox({ + type: 'info', + buttons: [t('Restart Now'), t('Later')], + message: t('Update Downloaded'), + detail: t('updateIsDownloaded', {releaseName}), + }); + if (response === 0) { + autoUpdater.quitAndInstall(); + } +}); + +export function checkForUpdates() { + autoUpdater.checkForUpdates(); +} diff --git a/app/renderer/actions/Updater.js b/app/renderer/actions/Updater.js deleted file mode 100644 index f0a3f784c..000000000 --- a/app/renderer/actions/Updater.js +++ /dev/null @@ -1,7 +0,0 @@ -export const SET_UPDATE_STATE = 'SET_UPDATE_STATE'; - -export function setUpdateState(updateState) { - return (dispatch) => { - dispatch({type: SET_UPDATE_STATE, updateState}); - }; -} diff --git a/app/renderer/actions/index.js b/app/renderer/actions/index.js index 0fc52134b..523a4fd39 100644 --- a/app/renderer/actions/index.js +++ b/app/renderer/actions/index.js @@ -1,9 +1,7 @@ import * as inspectorActions from './Inspector'; import * as sessionActions from './Session'; -import * as updaterActions from './Updater'; export default { ...inspectorActions, ...sessionActions, - ...updaterActions, }; diff --git a/app/renderer/reducers/Updater.js b/app/renderer/reducers/Updater.js deleted file mode 100644 index 1d106de53..000000000 --- a/app/renderer/reducers/Updater.js +++ /dev/null @@ -1,12 +0,0 @@ -import {SET_UPDATE_STATE} from '../actions/Updater'; - -const INITIAL_STATE = {}; - -export default function session(state = INITIAL_STATE, action) { - switch (action.type) { - case SET_UPDATE_STATE: - return {...action.updateState}; - default: - return {...state}; - } -} diff --git a/app/renderer/reducers/index.js b/app/renderer/reducers/index.js index 5abbcf541..8748113c2 100644 --- a/app/renderer/reducers/index.js +++ b/app/renderer/reducers/index.js @@ -2,13 +2,11 @@ import {combineReducers} from '@reduxjs/toolkit'; import inspector from './Inspector'; import session from './Session'; -import updater from './Updater'; // create our root reducer export default function createRootReducer() { return combineReducers({ session, inspector, - updater, }); } diff --git a/assets/locales/en/translation.json b/assets/locales/en/translation.json index 886930c6b..4a9aef0f9 100644 --- a/assets/locales/en/translation.json +++ b/assets/locales/en/translation.json @@ -41,7 +41,6 @@ "Save Server Arguments Preset": "Save Server Arguments Preset", "Save": "Save", "Cancel": "Cancel", - "datetimeFormat": "MMM Do YYYY, h:mma", "updateDetails": "Release Date: {{pubDate}}\n\nRelease Notes: {{notes}}", "appiumIsAvailable": "Appium Inspector {{name}} is available", "updateIsBeingDownloaded": "Update is being downloaded now. You will be notified again when it is complete", diff --git a/docs/menu-bar.md b/docs/menu-bar.md index 2ced37356..814577b81 100644 --- a/docs/menu-bar.md +++ b/docs/menu-bar.md @@ -19,14 +19,16 @@ However, there are a few specific options as well: ## Update Checker -!!! warning - - [This functionality is currently unavailable.](./troubleshooting.md#auto-updater-not-working) - The update checker is available under the _File_ menu (Windows/Linux) or the application menu (macOS). It can be used to check if there is a newer version of the Inspector available, and if so, it is possible to automatically download and install the latest version. +Updating is supported for the following application formats: + +- macOS: `.dmg` +- Windows: `.exe` installer +- Linux: `.AppImage` + ## Open/Save Session The _Open Session File_ / _Save As_ options in the _File_ menu provides the ability to import and diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index af4de0751..ec6871b6f 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -11,11 +11,6 @@ This page aims to act as a reference for issues that may be encountered when usi Please refer to the [Installation guide](./quickstart/installation.md). -## Auto-updater not working - -This is [a known issue](https://github.com/appium/appium-inspector/issues/733) and is planned to be -fixed in future versions. - ## Cannot start a session using browser Inspector The reason for this issue is [cross-origin resource sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) diff --git a/env/.env-dev.js b/env/.env-dev.js deleted file mode 100644 index ff8b4c563..000000000 --- a/env/.env-dev.js +++ /dev/null @@ -1 +0,0 @@ -export default {}; diff --git a/env/.env-nsis.js b/env/.env-nsis.js deleted file mode 100644 index de107458b..000000000 --- a/env/.env-nsis.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Env configuration for NSIS target - */ -module.exports = { - NO_AUTO_UPDATE: true, -}; diff --git a/env/.env.js b/env/.env.js deleted file mode 100644 index 8eaedbbd3..000000000 --- a/env/.env.js +++ /dev/null @@ -1,7 +0,0 @@ -let env = {}; - -if (process.env.TARGET) { - env = require(`./.env-${process.env.TARGET}`); -} - -export default env; diff --git a/package-lock.json b/package-lock.json index e769bcf65..57e54f151 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,6 @@ "react-icons": "5.0.1", "react-redux": "9.1.0", "react-router-dom": "6.22.3", - "semver": "7.6.0", "uuid": "9.0.1", "web2driver": "3.0.4", "xpath": "0.0.34" diff --git a/package.json b/package.json index 649f90728..d45e92a3c 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,6 @@ "react-icons": "5.0.1", "react-redux": "9.1.0", "react-router-dom": "6.22.3", - "semver": "7.6.0", "uuid": "9.0.1", "web2driver": "3.0.4", "xpath": "0.0.34" diff --git a/test/integration/update-checker.integration-test.js b/test/integration/update-checker.integration-test.js deleted file mode 100644 index 9ad50a7f1..000000000 --- a/test/integration/update-checker.integration-test.js +++ /dev/null @@ -1,46 +0,0 @@ -import axios from 'axios'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import sinon from 'sinon'; - -import {checkUpdate} from '../../app/main/auto-updater/update-checker'; - -chai.should(); -chai.use(chaiAsPromised); - -// TODO: Fix this once pipelines is fully working -describe.skip('updateChecker', function () { - let latestVersion; - - before(async function () { - if (!process.env.GITHUB_TOKEN) { - return this.skip(); - } - const latestReleaseUrl = `https://api.github.com/repos/appium/appium-inspector/releases/latest?access_token=${process.env.GITHUB_TOKEN}`; - const res = await axios({ - url: latestReleaseUrl, - headers: {'user-agent': 'node.js'}, - }); - latestVersion = res.name; - }); - - describe('.checkUpdate', function () { - it('not find anything if latest release is same as current release', async function () { - await checkUpdate(latestVersion).should.eventually.equal(false); - }); - it('should find something if latest release is different from current release', async function () { - const {name, notes, pub_date, url} = await checkUpdate('v0.0.0'); - name.should.be.a.string; - notes.should.be.a.string; - pub_date.should.be.a.string; - url.should.be.a.string; - }); - it('should return false if request for update throws error', async function () { - let promiseStub = sinon.stub(axios, 'get', () => { - throw new Error(`Failed Request`); - }); - await checkUpdate('v0.0.0').should.eventually.be.false; - promiseStub.restore(); - }); - }); -});