Switch things to typescript, use @types/modernizr, fix global.d.ts. Move mobile_guide redirect to index.ts
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
093b7bbf72
commit
b1575524aa
8 changed files with 92 additions and 72 deletions
|
@ -96,6 +96,7 @@
|
|||
"@babel/preset-typescript": "^7.7.4",
|
||||
"@babel/register": "^7.7.4",
|
||||
"@babel/runtime": "^7.7.6",
|
||||
"@types/modernizr": "^3.5.3",
|
||||
"@types/react": "16.9",
|
||||
"@types/react-dom": "^16.9.4",
|
||||
"autoprefixer": "^9.7.3",
|
||||
|
|
24
src/@types/global.d.ts
vendored
24
src/@types/global.d.ts
vendored
|
@ -14,12 +14,22 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
type ReactNode = import("react").ReactNode;
|
||||
import {ReactNode} from "react";
|
||||
import "modernizr";
|
||||
|
||||
interface Window {
|
||||
Olm: {
|
||||
init: () => Promise<void>;
|
||||
};
|
||||
mxSendRageshake: (text: string, withLogs?: boolean) => void;
|
||||
matrixChat: ReactNode;
|
||||
declare global {
|
||||
interface Window {
|
||||
Modernizr: ModernizrAPI & FeatureDetects;
|
||||
Olm: {
|
||||
init: () => Promise<void>;
|
||||
};
|
||||
|
||||
mxSendRageshake: (text: string, withLogs?: boolean) => void;
|
||||
matrixChat: ReactNode;
|
||||
}
|
||||
|
||||
// workaround for https://github.com/microsoft/TypeScript/issues/30933
|
||||
interface ObjectConstructor {
|
||||
fromEntries?(xs: [string|number|symbol, any][]): object
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,41 +44,6 @@ import {loadConfig, preparePlatform, loadLanguage, loadOlm} from "./init";
|
|||
|
||||
let lastLocationHashSet = null;
|
||||
|
||||
function checkBrowserFeatures() {
|
||||
if (!window.Modernizr) {
|
||||
console.error("Cannot check features - Modernizr global is missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// custom checks atop Modernizr because it doesn't have ES2018/ES2019 checks in it for some features we depend on,
|
||||
// Modernizr requires rules to be lowercase with no punctuation:
|
||||
// ES2018: http://www.ecma-international.org/ecma-262/9.0/#sec-promise.prototype.finally
|
||||
window.Modernizr.addTest("promiseprototypefinally", () =>
|
||||
window.Promise && window.Promise.prototype && typeof window.Promise.prototype.finally === "function");
|
||||
// ES2019: http://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries
|
||||
window.Modernizr.addTest("objectfromentries", () =>
|
||||
window.Object && typeof window.Object.fromEntries === "function");
|
||||
|
||||
const featureList = Object.keys(window.Modernizr);
|
||||
|
||||
let featureComplete = true;
|
||||
for (let i = 0; i < featureList.length; i++) {
|
||||
if (window.Modernizr[featureList[i]] === undefined) {
|
||||
console.error(
|
||||
"Looked for feature '%s' but Modernizr has no results for this. " +
|
||||
"Has it been configured correctly?", featureList[i],
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (window.Modernizr[featureList[i]] === false) {
|
||||
console.error("Browser missing feature: '%s'", featureList[i]);
|
||||
// toggle flag rather than return early so we log all missing features rather than just the first.
|
||||
featureComplete = false;
|
||||
}
|
||||
}
|
||||
return featureComplete;
|
||||
}
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
function getScreenFromLocation(location) {
|
||||
|
@ -163,7 +128,7 @@ function onTokenLoginCompleted() {
|
|||
window.location.href = formatted;
|
||||
}
|
||||
|
||||
export async function loadApp() {
|
||||
export async function loadApp(fragParams: {}, acceptBrowser: boolean) {
|
||||
// XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack
|
||||
// but alternatives seem to require changing the interface to passing Workers to js-sdk
|
||||
const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript;
|
||||
|
@ -191,26 +156,8 @@ export async function loadApp() {
|
|||
// Load language after loading config.json so that settingsDefaults.language can be applied
|
||||
await loadLanguage();
|
||||
|
||||
const fragparts = parseQsFromFragment(window.location);
|
||||
const params = parseQs(window.location);
|
||||
|
||||
// don't try to redirect to the native apps if we're
|
||||
// verifying a 3pid (but after we've loaded the config)
|
||||
// or if the user is following a deep link
|
||||
// (https://github.com/vector-im/riot-web/issues/7378)
|
||||
const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0;
|
||||
|
||||
if (!preventRedirect) {
|
||||
const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
const isAndroid = /Android/.test(navigator.userAgent);
|
||||
if (isIos || isAndroid) {
|
||||
if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) {
|
||||
window.location = "mobile_guide/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as quickly as we possibly can, set a default theme...
|
||||
await setTheme();
|
||||
|
||||
|
@ -237,17 +184,13 @@ export async function loadApp() {
|
|||
return <GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />;
|
||||
}
|
||||
|
||||
const validBrowser = checkBrowserFeatures();
|
||||
|
||||
const acceptInvalidBrowser = window.localStorage && window.localStorage.getItem('mx_accepts_unsupported_browser');
|
||||
|
||||
const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
console.log("Vector starting at " + urlWithoutQuery);
|
||||
if (configError) {
|
||||
return <div className="error">
|
||||
Unable to load config file: please refresh the page to try again.
|
||||
</div>;
|
||||
} else if (validBrowser || acceptInvalidBrowser) {
|
||||
} else if (acceptBrowser) {
|
||||
platform.startUpdater();
|
||||
|
||||
try {
|
||||
|
@ -260,7 +203,7 @@ export async function loadApp() {
|
|||
ConferenceHandler={VectorConferenceHandler}
|
||||
config={config}
|
||||
realQueryParams={params}
|
||||
startingFragmentQueryParams={fragparts.params}
|
||||
startingFragmentQueryParams={fragParams}
|
||||
enableGuest={!config.disable_guests}
|
||||
onTokenLoginCompleted={onTokenLoginCompleted}
|
||||
initialScreenAfterLogin={getScreenFromLocation(window.location)}
|
||||
|
|
|
@ -25,6 +25,7 @@ require('gfm.css/gfm.css');
|
|||
require('highlight.js/styles/github.css');
|
||||
|
||||
// These are things that can run before the skin loads - be careful not to reference the react-sdk though.
|
||||
import {parseQsFromFragment} from "./url_utils";
|
||||
import './modernizr';
|
||||
|
||||
// load service worker if available on this platform
|
||||
|
@ -40,6 +41,41 @@ async function settled(prom: Promise<any>) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkBrowserFeatures() {
|
||||
if (!window.Modernizr) {
|
||||
console.error("Cannot check features - Modernizr global is missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// custom checks atop Modernizr because it doesn't have ES2018/ES2019 checks in it for some features we depend on,
|
||||
// Modernizr requires rules to be lowercase with no punctuation:
|
||||
// ES2018: http://www.ecma-international.org/ecma-262/9.0/#sec-promise.prototype.finally
|
||||
window.Modernizr.addTest("promiseprototypefinally", () =>
|
||||
window.Promise && window.Promise.prototype && typeof window.Promise.prototype.finally === "function");
|
||||
// ES2019: http://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries
|
||||
window.Modernizr.addTest("objectfromentries", () =>
|
||||
window.Object && typeof window.Object.fromEntries === "function");
|
||||
|
||||
const featureList = Object.keys(window.Modernizr);
|
||||
|
||||
let featureComplete = true;
|
||||
for (let i = 0; i < featureList.length; i++) {
|
||||
if (window.Modernizr[featureList[i]] === undefined) {
|
||||
console.error(
|
||||
"Looked for feature '%s' but Modernizr has no results for this. " +
|
||||
"Has it been configured correctly?", featureList[i],
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (window.Modernizr[featureList[i]] === false) {
|
||||
console.error("Browser missing feature: '%s'", featureList[i]);
|
||||
// toggle flag rather than return early so we log all missing features rather than just the first.
|
||||
featureComplete = false;
|
||||
}
|
||||
}
|
||||
return featureComplete;
|
||||
}
|
||||
|
||||
// React depends on Map & Set which we check for using modernizr's es6collections
|
||||
// if modernizr fails we may not have a functional react to show the error message.
|
||||
// try in react but fallback to an `alert`
|
||||
|
@ -52,11 +88,35 @@ async function start() {
|
|||
|
||||
await settled(rageshakePromise); // give rageshake a chance to load/fail
|
||||
|
||||
const fragparts = parseQsFromFragment(window.location);
|
||||
|
||||
// don't try to redirect to the native apps if we're
|
||||
// verifying a 3pid (but after we've loaded the config)
|
||||
// or if the user is following a deep link
|
||||
// (https://github.com/vector-im/riot-web/issues/7378)
|
||||
const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0;
|
||||
|
||||
if (!preventRedirect) {
|
||||
const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
const isAndroid = /Android/.test(navigator.userAgent);
|
||||
if (isIos || isAndroid) {
|
||||
if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) {
|
||||
window.location.href = "mobile_guide/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await loadSkin();
|
||||
|
||||
let acceptBrowser = checkBrowserFeatures();
|
||||
if (!acceptBrowser && window.localStorage) {
|
||||
acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser"));
|
||||
}
|
||||
|
||||
// Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to
|
||||
// run on the components. We use `require` here to make sure webpack doesn't optimize this into an async
|
||||
// import and thus running before the skin can load.
|
||||
await loadApp();
|
||||
await loadApp(fragparts.params, acceptBrowser);
|
||||
}
|
||||
start();
|
||||
|
|
|
@ -138,11 +138,12 @@ export async function loadSkin() {
|
|||
console.log("Skin loaded!");
|
||||
}
|
||||
|
||||
export async function loadApp() {
|
||||
export async function loadApp(fragParams: {}, acceptBrowser: boolean) {
|
||||
// load app.js async so that its code is not executed immediately and we can catch any exceptions
|
||||
const module = await import(
|
||||
/* webpackChunkName: "riot-web-app" */
|
||||
/* webpackPreload: true */
|
||||
"./app");
|
||||
window.matrixChat = ReactDOM.render(await module.loadApp(), document.getElementById('matrixchat'));
|
||||
window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser),
|
||||
document.getElementById('matrixchat'));
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ export function parseQsFromFragment(location: Location) {
|
|||
|
||||
const result = {
|
||||
location: decodeURIComponent(hashparts[0]),
|
||||
params: {},
|
||||
params: <qs.ParsedUrlQuery>{},
|
||||
};
|
||||
|
||||
if (hashparts.length > 1) {
|
||||
|
|
|
@ -31,7 +31,7 @@ module.exports = (env, argv) => {
|
|||
...development,
|
||||
|
||||
entry: {
|
||||
"bundle": "./src/vector/index.js",
|
||||
"bundle": "./src/vector/index.ts",
|
||||
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
|
||||
"mobileguide": "./src/vector/mobile_guide/index.js",
|
||||
"jitsi": "./src/vector/jitsi/index.ts",
|
||||
|
|
|
@ -1245,6 +1245,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/modernizr@^3.5.3":
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/modernizr/-/modernizr-3.5.3.tgz#8ef99e6252191c1d88647809109dc29884ba6d7a"
|
||||
integrity sha512-jhMOZSS0UGYTS9pqvt6q3wtT3uvOSve5piTEmTMx3zzTuBLvSIMxSIBIc3d5lajVD5h4xc41AMZD2M5orN3PxA==
|
||||
|
||||
"@types/node@*":
|
||||
version "13.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.0.tgz#5b6ee7a77faacddd7de719017d0bc12f52f81589"
|
||||
|
|
Loading…
Reference in a new issue