add startup daemon version check, refactor daemon versioning to package.json

This commit is contained in:
Jeremy Kauffman 2017-07-19 17:05:08 -04:00
parent 5aa471a68f
commit 38fd451e72
17 changed files with 156 additions and 24 deletions

View file

@ -27,7 +27,7 @@ const {version: localVersion} = require(app.getAppPath() + '/package.json');
const VERSION_CHECK_INTERVAL = 30 * 60 * 1000;
const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest';
const DAEMON_PATH = process.env.LBRY_DAEMON || path.join(__dirname, 'dist', 'lbrynet-daemon');
let client = jayson.client.http({
host: 'localhost',
@ -207,13 +207,8 @@ function handleDaemonSubprocessExited() {
function launchDaemon() {
assert(!daemonSubprocess, 'Tried to launch daemon twice');
if (process.env.LBRY_DAEMON) {
executable = process.env.LBRY_DAEMON;
} else {
executable = path.join(__dirname, 'dist', 'lbrynet-daemon');
}
console.log('Launching daemon:', executable)
daemonSubprocess = child_process.spawn(executable)
console.log('Launching daemon:', DAEMON_PATH)
daemonSubprocess = child_process.spawn(DAEMON_PATH)
// Need to handle the data event instead of attaching to
// process.stdout because the latter doesn't work. I believe on
// windows it buffers stdout and we don't get any meaningful output

View file

@ -18,5 +18,8 @@
},
"devDependencies": {
"electron-rebuild": "^1.5.11"
},
"lbrySettings": {
"lbrynetDaemonVersion": "0.14.1"
}
}

View file

@ -1 +0,0 @@
https://github.com/lbryio/lbry/releases/download/v0.14.1/lbrynet-daemon-v0.14.1-OSNAME.zip

View file

@ -79,11 +79,14 @@ if $OSX; then
else
OSNAME="linux"
fi
DAEMON_URL="$(cat "$BUILD_DIR/DAEMON_URL" | sed "s/OSNAME/${OSNAME}/")"
DAEMON_VER=$(node -e "console.log(require(\"$ROOT/app/package.json\").lbrySettings.lbrynetDaemonVersion)")
DAEMON_URL="https://github.com/lbryio/lbry/releases/download/v${DAEMON_VER}/lbrynet-daemon-v${DAEMON_VER}-${OSNAME}.zip"
wget --quiet "$DAEMON_URL" -O "$BUILD_DIR/daemon.zip"
unzip "$BUILD_DIR/daemon.zip" -d "$ROOT/app/dist/"
rm "$BUILD_DIR/daemon.zip"
###################
# Build the app #
###################

View file

@ -16,9 +16,9 @@ import { doFileList } from "actions/file_info";
const { remote, ipcRenderer, shell } = require("electron");
const path = require("path");
const app = require("electron").remote.app;
const { download } = remote.require("electron-dl");
const fs = remote.require("fs");
const { lbrySettings: config } = require("../../../app/package.json");
const queryStringFromParams = params => {
return Object.keys(params).map(key => `${key}=${params[key]}`).join("&");
@ -137,8 +137,9 @@ export function doDownloadUpgrade() {
return function(dispatch, getState) {
const state = getState();
// Make a new directory within temp directory so the filename is guaranteed to be available
const dir = fs.mkdtempSync(app.getPath("temp") + require("path").sep);
const upgradeFilename = selectUpgradeFilename(state);
const dir = fs.mkdtempSync(
remote.app.getPath("temp") + require("path").sep
);
let options = {
onProgress: p => dispatch(doUpdateDownloadProgress(Math.round(p * 100))),
@ -222,6 +223,18 @@ export function doCheckUpgradeAvailable() {
};
}
export function doCheckDaemonVersion() {
return function(dispatch, getState) {
lbry.version().then(({ lbrynet_version }) => {
dispatch({
type: config.lbrynetDaemonVersion == lbrynet_version
? types.DAEMON_VERSION_MATCH
: types.DAEMON_VERSION_MISMATCH,
});
});
};
}
export function doAlertError(errorList) {
return function(dispatch, getState) {
const state = getState();
@ -269,3 +282,10 @@ export function doClearCache() {
return Promise.resolve();
};
}
export function doQuitAndLaunchDaemonHelp() {
return function(dispatch, getState) {
shell.openExternal("https://lbry.io/faq/incompatible-protocol-version");
remote.app.quit();
};
}

View file

@ -2,7 +2,9 @@ import store from "store.js";
import lbry from "./lbry.js";
const env = ENV;
const config = require(`./config/${env}`);
const config = {
...require(`./config/${env}`),
};
const language = lbry.getClientSetting("language")
? lbry.getClientSetting("language")
: "en";

View file

@ -6,6 +6,7 @@ import {
doCheckUpgradeAvailable,
doAlertError,
doRecordScroll,
doCheckDaemonVersion,
} from "actions/app";
import { doUpdateBalance } from "actions/wallet";
import App from "./view";

View file

@ -0,0 +1,13 @@
import React from "react";
import { connect } from "react-redux";
import { doQuit, doSkipWrongDaemonNotice } from "actions/app";
import { doQuitAndLaunchDaemonHelp } from "actions/app";
import ModalIncompatibleDaemon from "./view";
const select = state => ({});
const perform = dispatch => ({
quitAndLaunchDaemonHelp: () => dispatch(doQuitAndLaunchDaemonHelp()),
});
export default connect(select, perform)(ModalIncompatibleDaemon);

View file

@ -0,0 +1,24 @@
import React from "react";
import { Modal } from "component/modal";
class ModalIncompatibleDaemon extends React.PureComponent {
render() {
const { quitAndLaunchDaemonHelp } = this.props;
return (
<Modal
isOpen={true}
contentLabel={__("Incompatible daemon running")}
type="alert"
confirmButtonLabel={__("Quit and Learn More")}
onConfirmed={quitAndLaunchDaemonHelp}
>
{__(
"This browser is running with an incompatible version of the LBRY protocol and your install must be repaired."
)}
</Modal>
);
}
}
export default ModalIncompatibleDaemon;

View file

@ -0,0 +1,19 @@
import React from "react";
import { connect } from "react-redux";
import { selectCurrentModal, selectDaemonVersionMatched } from "selectors/app";
import { doCheckDaemonVersion } from "actions/app";
import SplashScreen from "./view";
const select = state => {
return {
modal: selectCurrentModal(state),
daemonVersionMatched: selectDaemonVersionMatched(state),
};
};
const perform = dispatch => ({
checkDaemonVersion: () => dispatch(doCheckDaemonVersion()),
});
export default connect(select, perform)(SplashScreen);

View file

@ -1,6 +1,9 @@
import React from "react";
import lbry from "../lbry.js";
import LoadScreen from "./load_screen.js";
import lbry from "../../lbry.js";
import LoadScreen from "../load_screen.js";
import ModalIncompatibleDaemon from "../modalIncompatibleDaemon";
import ModalUpgrade from "component/modalUpgrade";
import ModalDownloading from "component/modalDownloading";
export class SplashScreen extends React.PureComponent {
static propTypes = {
@ -14,6 +17,7 @@ export class SplashScreen extends React.PureComponent {
this.state = {
details: __("Starting daemon"),
message: __("Connecting"),
isRunning: false,
isLagging: false,
};
}
@ -35,10 +39,16 @@ export class SplashScreen extends React.PureComponent {
message: __("Testing Network"),
details: __("Waiting for name resolution"),
isLagging: false,
isRunning: true,
});
lbry.resolve({ uri: "lbry://one" }).then(() => {
this.props.onLoadDone();
// Only leave the load screen if the daemon version matched;
// otherwise we'll notify the user at the end of the load screen.
if (this.props.daemonVersionMatched) {
this.props.onReadyToLaunch();
}
});
return;
}
@ -54,6 +64,7 @@ export class SplashScreen extends React.PureComponent {
componentDidMount() {
lbry
.connect()
.then(this.props.checkDaemonVersion)
.then(() => {
this.updateStatus();
})
@ -69,12 +80,24 @@ export class SplashScreen extends React.PureComponent {
}
render() {
const { modal } = this.props;
return (
<LoadScreen
message={this.state.message}
details={this.state.details}
isWarning={this.state.isLagging}
/>
<div>
<LoadScreen
message={this.state.message}
details={this.state.details}
isWarning={this.state.isLagging}
/>
{/* Temp hack: don't show any modals on splash screen daemon is running;
daemon doesn't let you quit during startup, so the "Quit" buttons
in the modals won't work. */}
{modal == "incompatibleDaemon" &&
this.state.isRunning &&
<ModalIncompatibleDaemon />}
{modal == "upgrade" && this.state.isRunning && <ModalUpgrade />}
{modal == "downloading" && this.state.isRunning && <ModalDownloading />}
</div>
);
}
}

View file

@ -7,6 +7,8 @@ export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
export const DAEMON_READY = "DAEMON_READY";
export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH";
export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH";
// Upgrades
export const UPGRADE_CANCELLED = "UPGRADE_CANCELLED";

View file

@ -1,2 +1,3 @@
export const WELCOME = "welcome";
export const CONFIRM_FILE_REMOVE = "confirmFileRemove";
export const INCOMPATIBLE_DAEMON = "incompatibleDaemon";

View file

@ -5,7 +5,7 @@ import App from "component/app/index.js";
import SnackBar from "component/snackBar";
import { Provider } from "react-redux";
import store from "store.js";
import SplashScreen from "component/splash.js";
import SplashScreen from "component/splash";
import AuthOverlay from "component/authOverlay";
import { doChangePath, doNavigate, doDaemonReady } from "actions/app";
import { toQueryString } from "util/query_params";
@ -126,7 +126,12 @@ var init = function() {
if (window.sessionStorage.getItem("loaded") == "y") {
onDaemonReady();
} else {
ReactDOM.render(<SplashScreen onLoadDone={onDaemonReady} />, canvas);
ReactDOM.render(
<Provider store={store}>
<SplashScreen onReadyToLaunch={onDaemonReady} />
</Provider>,
canvas
);
}
};

View file

@ -1,4 +1,5 @@
import * as types from "constants/action_types";
import * as modalTypes from "constants/modal_types";
import lbry from "lbry";
const currentPath = () => {
@ -17,6 +18,7 @@ const defaultState = {
currentPath: currentPath(),
platform: process.platform,
upgradeSkipped: sessionStorage.getItem("upgradeSkipped"),
daemonVersionMatched: null,
daemonReady: false,
hasSignature: false,
badgeNumber: 0,
@ -28,6 +30,19 @@ reducers[types.DAEMON_READY] = function(state, action) {
});
};
reducers[types.DAEMON_VERSION_MATCH] = function(state, action) {
return Object.assign({}, state, {
daemonVersionMatched: true,
});
};
reducers[types.DAEMON_VERSION_MISMATCH] = function(state, action) {
return Object.assign({}, state, {
daemonVersionMatched: false,
modal: modalTypes.INCOMPATIBLE_DAEMON,
});
};
reducers[types.CHANGE_PATH] = function(state, action) {
return Object.assign({}, state, {
currentPath: action.data.path,

View file

@ -177,6 +177,11 @@ export const selectDaemonReady = createSelector(
state => state.daemonReady
);
export const selectDaemonVersionMatched = createSelector(
_selectState,
state => state.daemonVersionMatched
);
export const selectSnackBar = createSelector(
_selectState,
state => state.snackBar || {}

View file

@ -1,3 +1,5 @@
const { remote } = require("electron");
/**
* Thin wrapper around localStorage.getItem(). Parses JSON and returns undefined if the value
* is not set yet.