diff --git a/client/src/state/Settings/SettingsReducer.ts b/client/src/state/Settings/SettingsReducer.ts
index b47e547c4..de4ab37b1 100644
--- a/client/src/state/Settings/SettingsReducer.ts
+++ b/client/src/state/Settings/SettingsReducer.ts
@@ -17,7 +17,8 @@ export const initialState: ISettingsState = {
autoUpdates: false,
language: 'en',
email: '',
- token: ''
+ token: '',
+ allowPrerelease: false
};
export default function settingsReducer(
diff --git a/client/src/state/Settings/SettingsTypes.ts b/client/src/state/Settings/SettingsTypes.ts
index 2f9692ec0..d5cda4906 100644
--- a/client/src/state/Settings/SettingsTypes.ts
+++ b/client/src/state/Settings/SettingsTypes.ts
@@ -12,6 +12,7 @@ export interface ISettingsState {
language: string;
email: string;
token: string;
+ allowPrerelease: boolean;
}
export const SETTINGS_GET_SETTINGS_REQUEST = 'SETTINGS_GET_SETTINGS_REQUEST';
diff --git a/client/src/views/Launchpad.tsx b/client/src/views/Launchpad.tsx
index ef8f97dc9..23e06ea69 100644
--- a/client/src/views/Launchpad.tsx
+++ b/client/src/views/Launchpad.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { useDispatch } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { History } from 'history';
@@ -19,6 +19,7 @@ import { useTranslation } from 'react-i18next';
import MainSection from './components/MainSection';
import { Link } from 'react-router-dom';
+import { IState } from '../state';
import { track } from '../state/track/actions';
declare var window: {
@@ -63,6 +64,9 @@ export default function Launchpad() {
const { t } = useTranslation();
const dispatch = useDispatch();
const history = useHistory();
+ const allowPrerelease = useSelector(
+ (state: IState) => state.settings.allowPrerelease
+ );
window.h = history;
@@ -207,57 +211,61 @@ export default function Launchpad() {
-
-
-
-
-
-
-
-
-
+
+
+
+
- Lumi Run
-
-
+
+
+
+ Lumi Run (Beta)
+
+
+ {t('run.description')}
+
+
+
+
+
+
-
+ {t('analytics.startPage.start')}
+
+
+
+
+
+ )}
diff --git a/client/src/views/components/RunSetupDialog.tsx b/client/src/views/components/RunSetupDialog.tsx
index 3db88951d..d5f641cc2 100644
--- a/client/src/views/components/RunSetupDialog.tsx
+++ b/client/src/views/components/RunSetupDialog.tsx
@@ -120,7 +120,7 @@ export default function RunSetupDialog(props: IRunSetupDialogProps) {
open={open}
>
- Lumi Run
+ Lumi Run (Beta)
{t('run.description')}
diff --git a/client/src/views/components/Settings/GeneralSettingsList.tsx b/client/src/views/components/Settings/GeneralSettingsList.tsx
index ad24859ab..ac0515cc4 100644
--- a/client/src/views/components/Settings/GeneralSettingsList.tsx
+++ b/client/src/views/components/Settings/GeneralSettingsList.tsx
@@ -15,6 +15,7 @@ import BugReportIcon from '@material-ui/icons/BugReport';
import InsertChartIcon from '@material-ui/icons/InsertChart';
import TranslateIcon from '@material-ui/icons/Translate';
+import UpdateIcon from '@material-ui/icons/Update';
import { actions, IState } from '../../../state';
import LanguageList from './LanguageList';
@@ -95,6 +96,33 @@ export default function SettingsGeneralSettingsList() {
/>
+
+
+
+
+
+
+
+ dispatch(
+ actions.settings.changeSetting({
+ allowPrerelease: !settings.allowPrerelease
+ })
+ )
+ }
+ checked={settings.allowPrerelease}
+ inputProps={{
+ 'aria-labelledby':
+ 'switch-list-label-prerelease-updates'
+ }}
+ />
+
+
diff --git a/locales/lumi/en.json b/locales/lumi/en.json
index 0b0e55dc5..e7914a17a 100644
--- a/locales/lumi/en.json
+++ b/locales/lumi/en.json
@@ -12,6 +12,10 @@
},
"messages": { "econnrefused": "Connection Refused" }
},
+ "prerelease": {
+ "title": "Prerelease Features",
+ "description": "Enable experimental features before they are released"
+ },
"auth": {
"set_email": "Set Email",
"email": "Email",
diff --git a/server/src/boot/defaultSettings.ts b/server/src/boot/defaultSettings.ts
index ff690a965..7be4963f3 100644
--- a/server/src/boot/defaultSettings.ts
+++ b/server/src/boot/defaultSettings.ts
@@ -9,5 +9,6 @@ export default {
autoUpdates: false,
language: 'en',
email: '',
- token: ''
+ token: '',
+ allowPrerelease: false
};
diff --git a/server/src/settingsCache.ts b/server/src/settingsCache.ts
index 44c5c1fa2..b6f899b32 100644
--- a/server/src/settingsCache.ts
+++ b/server/src/settingsCache.ts
@@ -1,4 +1,5 @@
interface ISettingsState {
+ allowPrerelease: boolean;
autoUpdates: boolean;
bugTracking: boolean;
email: string;
diff --git a/server/src/updater.ts b/server/src/updater.ts
index 2e7da01c0..9b6866bcc 100644
--- a/server/src/updater.ts
+++ b/server/src/updater.ts
@@ -4,6 +4,7 @@ import SocketIO from 'socket.io';
import * as Sentry from '@sentry/electron';
import fsExtra from 'fs-extra';
import IServerConfig from './IServerConfig';
+import settingsCache from './settingsCache';
let updateAvailable: boolean = false;
let updating: boolean = false;
@@ -31,6 +32,8 @@ export default async function boot(
websocket: SocketIO.Server,
serverConfig: IServerConfig
): Promise {
+ autoUpdater.allowPrerelease = settingsCache.getSettings().allowPrerelease;
+
autoUpdater.on('update-downloaded', async () => {
updateAvailable = true;