diff --git a/website/package.json b/website/package.json index 4f6da151..edf28d7d 100644 --- a/website/package.json +++ b/website/package.json @@ -73,6 +73,7 @@ "react-dom": "^16.8.1", "react-helmet-async": "^0.2.0", "react-redux": "^6.0.0", + "react-resizable-panels": "^2.0.9", "react-resize-detector": "^6.7.4", "react-router-dom": "^4.4.0-beta.6", "react-simple-code-editor": "^0.11.0", diff --git a/website/src/client/components/DevicePreview/AppetizeFrame.tsx b/website/src/client/components/DevicePreview/AppetizeFrame.tsx index b6085b86..823f162f 100644 --- a/website/src/client/components/DevicePreview/AppetizeFrame.tsx +++ b/website/src/client/components/DevicePreview/AppetizeFrame.tsx @@ -226,10 +226,13 @@ function resolveAppetizePopupUrl(config: AppetizeSdkConfig) { const styles = StyleSheet.create({ container: { position: 'relative', - height: 672, + height: '100%', + width: '100%', overflow: 'hidden', margin: 'auto', zIndex: 2, + padding: 32, + boxSizing: 'border-box', }, containerEmbedded: { position: 'relative', @@ -241,5 +244,6 @@ const styles = StyleSheet.create({ frame: { border: 0, height: '100%', + width: '100%', }, }); diff --git a/website/src/client/components/DevicePreview/DevicePreview.tsx b/website/src/client/components/DevicePreview/DevicePreview.tsx index cd524b43..e29c9707 100644 --- a/website/src/client/components/DevicePreview/DevicePreview.tsx +++ b/website/src/client/components/DevicePreview/DevicePreview.tsx @@ -151,7 +151,7 @@ class DevicePreview extends React.PureComponent { return (
{isEmbedded ? null : (
@@ -218,9 +218,7 @@ export default withThemeName(DevicePreview); const styles = StyleSheet.create({ container: { position: 'relative', - maxWidth: '50%', - overflowX: 'hidden', - overflowY: 'auto', + width: '100%', display: 'none', flexDirection: 'column', diff --git a/website/src/client/components/DevicePreview/MyDeviceFrame.tsx b/website/src/client/components/DevicePreview/MyDeviceFrame.tsx index 7fa8a7ed..26f7e969 100644 --- a/website/src/client/components/DevicePreview/MyDeviceFrame.tsx +++ b/website/src/client/components/DevicePreview/MyDeviceFrame.tsx @@ -60,9 +60,10 @@ class MyDeviceFrame extends React.PureComponent { const { experienceURL, isEmbedded, width } = this.props; const { connectedDevices, copiedToClipboard } = this.state; const isConnected = connectedDevices.length >= 1; + const fixedWidthStyle = isEmbedded ? { width } : undefined; return ( -
+
Copied to clipboard!

@@ -265,6 +266,7 @@ const styles = StyleSheet.create({ borderRadius: 4, padding: 10, marginLeft: 10, + margin: '0 auto 16px auto', }, experienceLink: { cursor: 'pointer', diff --git a/website/src/client/components/EditorView.tsx b/website/src/client/components/EditorView.tsx index 900892a3..7158eee2 100644 --- a/website/src/client/components/EditorView.tsx +++ b/website/src/client/components/EditorView.tsx @@ -2,6 +2,7 @@ import { StyleSheet, css } from 'aphrodite'; import debounce from 'lodash/debounce'; import * as React from 'react'; import { connect } from 'react-redux'; +import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import AssetViewer from './AssetViewer'; import { withDependencyManager } from './DependencyManager'; @@ -35,6 +36,7 @@ import KeybindingsManager from './shared/KeybindingsManager'; import LazyLoad from './shared/LazyLoad'; import ModalDialog from './shared/ModalDialog'; import ProgressIndicator from './shared/ProgressIndicator'; +import constants from '../configs/constants'; import { Viewer, SnackFiles, Annotation, SDKVersion } from '../types'; import Analytics from '../utils/Analytics'; import { isMobile } from '../utils/detectPlatform'; @@ -78,6 +80,7 @@ type State = { lintedFiles: LintedFiles; lintAnnotations: Annotation[]; shouldPreventRedirectWarning: boolean; + isPanelResizing: boolean; }; const BANNER_TIMEOUT_SHORT = 1500; @@ -93,6 +96,7 @@ class EditorView extends React.Component { lintedFiles: {}, lintAnnotations: [], shouldPreventRedirectWarning: false, + isPanelResizing: false, }; static getDerivedStateFromProps(props: Props, state: State) { @@ -345,6 +349,12 @@ class EditorView extends React.Component { shouldPreventRedirectWarning: false, }); + onPanelResizing = (isDragging: boolean) => { + this.setState({ + isPanelResizing: isDragging, + }); + }; + render() { const { currentModal, currentBanner, lintAnnotations } = this.state; @@ -450,188 +460,214 @@ class EditorView extends React.Component { onDownloadCode={this.props.onDownloadAsync} onPublishAsync={onPublishAsync} /> -
-
- - - {/* Don't load it conditionally since we need the _EditorComponent object to be available */} - }> => { - if (isMobile(userAgent)) { - // Monaco doesn't work great on mobile` - // Use simple editor for better experience - const editor = await import('./Editor/SimpleEditor'); - this.setState({ loadedEditor: 'simple' }); - return editor; - } - - let timeout: any; - - const MonacoEditorPromise = import( - /* webpackPreload: true */ './Editor/MonacoEditor' - ).then((editor) => ({ editor, type: 'monaco' })); - - // Fallback to simple editor if monaco editor takes too long to load - const SimpleEditorPromise = new Promise((resolve, reject) => { - timeout = setTimeout(() => { - this._showBanner('slow-connection'); - - import('./Editor/SimpleEditor').then(resolve, reject); - }, EDITOR_LOAD_FALLBACK_TIMEOUT); - }).then((editor) => ({ editor, type: 'simple' })); - - return Promise.race([ - MonacoEditorPromise.catch(() => SimpleEditorPromise), - SimpleEditorPromise, - ]).then(({ editor, type }: any) => { - this.setState({ loadedEditor: type }); - - clearTimeout(timeout); - - return editor; - }); - }} - > - {({ loaded, data: Comp }) => { - this._EditorComponent = Comp; - const file = files[selectedFile]; - if (file) { - if (file.type === 'ASSET') { - return ; + + +
+ + + {/* Don't load it conditionally since we need the _EditorComponent object to be available */} + ; + }> => { + if (isMobile(userAgent)) { + // Monaco doesn't work great on mobile` + // Use simple editor for better experience + const editor = await import('./Editor/SimpleEditor'); + this.setState({ loadedEditor: 'simple' }); + return editor; } - const { contents } = file; - const isMarkdown = selectedFile.endsWith('.md'); - - if (isMarkdown && this.state.isMarkdownPreview) { - return ( - <> - import('./Markdown/MarkdownPreview')}> - {({ loaded: mdLoaded, data: MarkdownPreview }) => { - if (mdLoaded && MarkdownPreview) { - return ; - } - - return ; - }} - - - - ); - } - - if (loaded && Comp) { - return ( - <> - - {isMarkdown ? ( + let timeout: any; + + const MonacoEditorPromise = import( + /* webpackPreload: true */ './Editor/MonacoEditor' + ).then((editor) => ({ editor, type: 'monaco' })); + + // Fallback to simple editor if monaco editor takes too long to load + const SimpleEditorPromise = new Promise((resolve, reject) => { + timeout = setTimeout(() => { + this._showBanner('slow-connection'); + + import('./Editor/SimpleEditor').then(resolve, reject); + }, EDITOR_LOAD_FALLBACK_TIMEOUT); + }).then((editor) => ({ editor, type: 'simple' })); + + return Promise.race([ + MonacoEditorPromise.catch(() => SimpleEditorPromise), + SimpleEditorPromise, + ]).then(({ editor, type }: any) => { + this.setState({ loadedEditor: type }); + + clearTimeout(timeout); + + return editor; + }); + }} + > + {({ loaded, data: Comp }) => { + this._EditorComponent = Comp; + const file = files[selectedFile]; + if (file) { + if (file.type === 'ASSET') { + return ; + } + + const { contents } = file; + const isMarkdown = selectedFile.endsWith('.md'); + + if (isMarkdown && this.state.isMarkdownPreview) { + return ( + <> + import('./Markdown/MarkdownPreview')}> + {({ loaded: mdLoaded, data: MarkdownPreview }) => { + if (mdLoaded && MarkdownPreview) { + return ; + } + + return ; + }} + - ) : null} - - ); + + ); + } + + if (loaded && Comp) { + return ( + <> + + {isMarkdown ? ( + + ) : null} + + ); + } + } else { + return ; } - } else { - return ; - } - - return ; - }} - - - {preferences.panelsShown ? ( - - ) : null} -
+ + return ; + }} +
+
+ {preferences.panelsShown ? ( + + ) : null} +
+ {previewShown ? ( - + <> + +
+
+
+ + + + + ) : null} -
+ createAppetizeDeviceList(devices), [platform, devices]); + const deviceList = useMemo( + () => createAppetizeDeviceList(platform, devices), + [platform, devices] + ); useEffect(() => { if (!cachedAppetizeDevices) { @@ -48,14 +51,17 @@ export function useAppetizeDevices(platform: 'android' | 'ios') { return deviceList; } -function createAppetizeDeviceList(devices?: typeof cachedAppetizeDevices) { +function createAppetizeDeviceList( + platform: 'android' | 'ios', + devices?: typeof cachedAppetizeDevices +) { if (!devices) { return []; } return devices - .map((device) => ({ deviceName: device.name, deviceId: device.id })) - .filter(({ deviceId }) => !deviceId.includes('ipad') && !deviceId.includes('galaxytab')); + .filter((device) => device.platform === platform) + .map((device) => ({ deviceName: device.name, deviceId: device.id })); } async function fetchAppetizeDevices(): Promise { diff --git a/yarn.lock b/yarn.lock index 219eefdd..f1214584 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1355,7 +1355,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.23.3", "@babel/plugin-transform-typescript@^7.23.6", "@babel/plugin-transform-typescript@^7.5.0": +"@babel/plugin-transform-typescript@^7.13.0", "@babel/plugin-transform-typescript@^7.23.3", "@babel/plugin-transform-typescript@^7.5.0": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c" integrity sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA== @@ -1598,7 +1598,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.17.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.17.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== @@ -4730,7 +4730,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-core@^7.0.0-bridge.0: +babel-core@7.0.0-bridge.0, babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== @@ -13859,6 +13859,11 @@ react-refresh@^0.14.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== +react-resizable-panels@^2.0.9: + version "2.0.9" + resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.0.9.tgz#35acd8116475ebebb916c1559e75de3594004546" + integrity sha512-ZylBvs7oG7Y/INWw3oYGolqgpFvoPW8MPeg9l1fURDeKpxrmUuCHBUmPj47BdZ11MODImu3kZYXG85rbySab7w== + react-resize-detector@^6.7.4: version "6.7.4" resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-6.7.4.tgz#594cc026115af05484e8011157b5dc2137492680"