forked from Hubs-Foundation/hubs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsupport.js
160 lines (149 loc) · 6.08 KB
/
support.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
NOTE: support.js needs to be as self-contained as possible, since it needs to work in legacy browers
that we do not support. Avoid adding imports to libraries or other modules from our own codebase
that might break the support UI in legacy browsers.
*/
import React from "react";
import ReactDOM from "react-dom";
import copy from "copy-to-clipboard";
import { detectOS } from "detect-browser";
import { FormattedMessage } from "react-intl";
import { WrappedIntlProvider } from "./react-components/wrapped-intl-provider";
import "./react-components/styles/global.scss";
import styles from "./assets/stylesheets/support.scss";
import configs from "./utils/configs";
import { ThemeProvider } from "./react-components/styles/theme";
const SHORTHAND_INITIALIZER = "var foo = 'bar'; var baz = { foo };";
const SPREAD_SYNTAX = "var foo = {}; var baz = { ...foo };";
const CATCH_SYNTAX = "try { foo(); } catch {}";
function syntaxSupported(syntax) {
try {
eval(syntax);
return true;
} catch (e) {
return false;
}
}
function getPlatformSupport() {
return [
{ name: "Web Assembly", supported: !!window.WebAssembly },
{ name: "Media Devices", supported: !!navigator.mediaDevices },
{ name: "Shorthand initializer syntax", supported: syntaxSupported(SHORTHAND_INITIALIZER) },
{ name: "Spread syntax", supported: syntaxSupported(SPREAD_SYNTAX) },
{ name: "Optional catch syntax", supported: syntaxSupported(CATCH_SYNTAX) }
];
}
function isInAppBrowser() {
// Some apps like Twitter, Discord and Facebook on Android and iOS open links in
// their own embedded preview browsers.
//
// On iOS this WebView does not have a mediaDevices API at all, but in Android apps
// like Facebook, the browser pretends to have a mediaDevices, but never actually
// prompts the user for device access. So, we show a dialog that tells users to open
// the room in an actual browser like Safari, Chrome or Firefox.
//
// Facebook Mobile Browser on Android has a userAgent like this:
// Mozilla/5.0 (Linux; Android 9; SM-G950U1 Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko)
// Version/4.0 Chrome/80.0.3987.149 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/262.0.0.34.117;]
const detectedOS = detectOS(navigator.userAgent);
return (detectedOS === "iOS" && !navigator.mediaDevices) || /\bfb_iab\b/i.test(navigator.userAgent);
}
export function platformUnsupported() {
return getPlatformSupport().some(s => !s.supported) || isInAppBrowser();
}
class Support extends React.Component {
state = { showDetails: false, hasCopied: false };
toggleDetails = e => {
e.preventDefault();
this.setState(state => {
state.showDetails = !state.showDetails;
return state;
});
};
onCopyClicked = e => {
e.preventDefault();
copy(document.location);
this.setState({ hasCopied: true });
};
render() {
const platformSupport = getPlatformSupport();
const allSupported = platformSupport.every(s => s.supported);
const inAppBrowser = isInAppBrowser();
if (allSupported && !inAppBrowser) return null;
const detectedOS = detectOS(navigator.userAgent);
return (
<WrappedIntlProvider>
<ThemeProvider>
<div className={styles.supportMain}>
<div className={styles.supportContent}>
<div>
<img className={styles.logo} src={configs.image("logo")} />
</div>
<p>
<FormattedMessage
id="support.missing-features"
defaultMessage="Your browser is missing required features."
/>
<br />
{inAppBrowser ? (
detectedOS === "iOS" ? (
<FormattedMessage
id="support.in-app-browser-ios"
defaultMessage="Copy and paste this link directly into Safari"
/>
) : (
<FormattedMessage
id="support.in-app-browser-android"
defaultMessage="Copy and paste this link directly into Chrome or Firefox"
/>
)
) : (
<FormattedMessage
id="support.update-browser"
defaultMessage="Please try switching or updating to a newer browser"
/>
)}
<br />
<br />
<input type="text" readOnly onFocus={e => e.target.select()} value={document.location} />
<a className="copy-link" href="#" onClick={this.onCopyClicked}>
{this.state.hasCopied ? (
<FormattedMessage id="support.copied" defaultMessage="copied!" />
) : (
<FormattedMessage id="support.copy" defaultMessage="copy" />
)}
</a>
<br />
<br />
<a className={styles.detailsLink} href="#" onClick={this.toggleDetails}>
<FormattedMessage id="support.details" defaultMessage="details" />
</a>
</p>
{this.state.showDetails && (
<table className={styles.details}>
<tbody>
{platformSupport.sort((a, b) => (a.supported && !b.supported ? 1 : -1)).map(s => (
<tr key={s.name}>
<td>{s.name}</td>
<td>
{s.supported ? (
<FormattedMessage id="support.supported" defaultMessage="supported" />
) : (
<FormattedMessage id="support.unsupported" defaultMessage="unsupported" />
)}
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
</div>
</ThemeProvider>
</WrappedIntlProvider>
);
}
}
document.addEventListener("DOMContentLoaded", () => {
ReactDOM.render(<Support />, document.getElementById("support-root"));
});