diff --git a/src/components/views/globals/NewVersionBar.js b/src/components/views/globals/NewVersionBar.js index 90b30f727b..36d6bc71bd 100644 --- a/src/components/views/globals/NewVersionBar.js +++ b/src/components/views/globals/NewVersionBar.js @@ -16,9 +16,10 @@ limitations under the License. 'use strict'; -var React = require('react'); -var sdk = require('matrix-react-sdk'); +import React from 'react'; +import sdk from 'matrix-react-sdk'; import Modal from 'matrix-react-sdk/lib/Modal'; +import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg'; /** * Check a version string is compatible with the Changelog @@ -29,37 +30,65 @@ function checkVersion(ver) { return parts[0] == 'vector' && parts[2] == 'react' && parts[4] == 'js'; } -export default function NewVersionBar(props) { - const onChangelogClicked = () => { - const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog'); +export default React.createClass({ + propTypes: { + version: React.PropTypes.string.isRequired, + newVersion: React.PropTypes.string.isRequired, + releaseNotes: React.PropTypes.string, + }, - Modal.createDialog(ChangelogDialog, { - version: props.version, - newVersion: props.newVersion, + displayReleaseNotes: function(releaseNotes) { + const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog'); + Modal.createDialog(QuestionDialog, { + title: "What's New", + description:
{releaseNotes}
, + button: "Update", onFinished: (update) => { - if(update) { - window.location.reload(); + if(update && PlatformPeg.get()) { + PlatformPeg.get().installUpdate(); } } }); - }; + }, - let changelog_button; - if (checkVersion(props.version) && checkVersion(props.newVersion)) { - changelog_button = ; - } - return ( -
- /!\ -
- A new version of Riot is available. Refresh your browser. + displayChangelog: function() { + const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog'); + Modal.createDialog(ChangelogDialog, { + version: this.props.version, + newVersion: this.props.newVersion, + onFinished: (update) => { + if(update && PlatformPeg.get()) { + PlatformPeg.get().installUpdate(); + } + } + }); + }, + + onUpdateClicked: function() { + PlatformPeg.get().installUpdate(); + }, + + render: function() { + let action_button; + // If we have release notes to display, we display them. Otherwise, + // we display the Changelog Dialog which takes two versions and + // automatically tells you what's changed (provided the versions + // are in the right format) + if (this.props.releaseNotes) { + action_button = ; + } else if (checkVersion(this.props.version) && checkVersion(this.props.newVersion)) { + action_button = ; + } else if (PlatformPeg.get()) { + action_button = ; + } + return ( +
+ /!\ +
+ A new version of Riot is available. +
+ {action_button}
- {changelog_button} -
- ); -} - -NewVersionBar.propTypes = { - version: React.PropTypes.string.isRequired, - newVersion: React.PropTypes.string.isRequired, -}; + ); + } +}); diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/common.css index 5165e9c57c..bb00bbd8c0 100644 --- a/src/skins/vector/css/common.css +++ b/src/skins/vector/css/common.css @@ -288,3 +288,7 @@ textarea { cursor: pointer; display: inline; } + +.changelog_text { + font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; +} diff --git a/src/vector/index.js b/src/vector/index.js index 5d00d07823..9454e6702e 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -113,10 +113,6 @@ function onHashChange(ev) { routeUrl(window.location); } -function onVersion(current, latest) { - window.matrixChat.onVersion(current, latest); -} - var loaded = false; var lastLoadedScreen = null; @@ -165,8 +161,7 @@ window.onload = function() { if (!validBrowser) { return; } - UpdateChecker.setVersionListener(onVersion); - UpdateChecker.run(); + UpdateChecker.start(); routeUrl(window.location); loaded = true; if (lastLoadedScreen) { diff --git a/src/vector/platform/VectorBasePlatform.js b/src/vector/platform/VectorBasePlatform.js new file mode 100644 index 0000000000..d2ed8c344c --- /dev/null +++ b/src/vector/platform/VectorBasePlatform.js @@ -0,0 +1,42 @@ +// @flow + +/* +Copyright 2016 Aviral Dasgupta +Copyright 2016 OpenMarket Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import BasePlatform from 'matrix-react-sdk/lib/BasePlatform' + +/** + * Vector-specific extensions to the BasePlatform template + */ +export default class VectorBasePlatform extends BasePlatform { + /** + * Check for the availability of an update to the version of the + * app that's currently running. + * If an update is available, this function should dispatch the + * 'new_version' action. + */ + pollForUpdate() { + } + + /** + * Update the currently running app to the latest available + * version and replace this instance of the app with the + * new version. + */ + installUpdate() { + } +} diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js index f4adbd5d54..4d99496729 100644 --- a/src/vector/platform/WebPlatform.js +++ b/src/vector/platform/WebPlatform.js @@ -17,14 +17,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import BasePlatform from 'matrix-react-sdk/lib/BasePlatform'; +import VectorBasePlatform from './VectorBasePlatform'; import Favico from 'favico.js'; +import request from 'browser-request'; import dis from 'matrix-react-sdk/lib/dispatcher.js'; import q from 'q'; -export default class WebPlatform extends BasePlatform { +export default class WebPlatform extends VectorBasePlatform { constructor() { super(); + this.runningVersion = null; // The 'animations' are really low framerate and look terrible. // Also it re-starts the animationb every time you set the badge, // and we set the state each time, even if the value hasn't changed, @@ -123,4 +125,42 @@ export default class WebPlatform extends BasePlatform { notification.close(); }, 5 * 1000); } + + _getVersion() { + const deferred = q.defer(); + request( + { method: "GET", url: "version" }, + (err, response, body) => { + if (err || response.status < 200 || response.status >= 300) { + if (err == null) err = { status: response.status }; + deferred.reject(err); + return; + } + + const ver = body.trim(); + deferred.resolve(ver); + } + ); + return deferred.promise; + } + + pollForUpdate() { + this._getVersion().done((ver) => { + if (this.runningVersion == null) { + this.runningVersion = ver; + } else if (this.runningVersion != ver) { + dis.dispatch({ + action: 'new_version', + currentVersion: this.runningVersion, + newVersion: ver, + }); + } + }, (err) => { + console.error("Failed to poll for update", err); + }); + } + + installUpdate() { + window.location.reload(); + } } diff --git a/src/vector/updater.js b/src/vector/updater.js index e8d6830d02..19d40b4f38 100644 --- a/src/vector/updater.js +++ b/src/vector/updater.js @@ -13,48 +13,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ + +import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg'; + var POKE_RATE_MS = 10 * 60 * 1000; // 10 min -var currentVersion = null; -var latestVersion = null; -var listener = function(){}; // NOP module.exports = { - setVersionListener: function(fn) { // invoked with fn(currentVer, newVer) - listener = fn; + start: function() { + module.exports.poll(); + setInterval(module.exports.poll, POKE_RATE_MS); }, - run: function() { - var req = new XMLHttpRequest(); - req.addEventListener("load", function() { - if (!req.responseText) { - return; - } - var ver = req.responseText.trim(); - if (!currentVersion) { - currentVersion = ver; - listener(currentVersion, currentVersion); - } - - if (ver !== latestVersion) { - latestVersion = ver; - if (module.exports.hasNewVersion()) { - console.log("Current=%s Latest=%s", currentVersion, latestVersion); - listener(currentVersion, latestVersion); - } - } - }); - var cacheBuster = "?ts=" + new Date().getTime(); - req.open("GET", "version" + cacheBuster); - req.send(); // can't suppress 404s from being logged. - - setTimeout(module.exports.run, POKE_RATE_MS); - }, - - getCurrentVersion: function() { - return currentVersion; - }, - - hasNewVersion: function() { - return currentVersion && latestVersion && (currentVersion !== latestVersion); + poll: function() { + PlatformPeg.get().pollForUpdate(); } };