diff --git a/server/images/android_screenshot.png b/server/images/android_screenshot.png deleted file mode 100644 index e131aa02d..000000000 Binary files a/server/images/android_screenshot.png and /dev/null differ diff --git a/server/images/android_screenshot@2x.png b/server/images/android_screenshot@2x.png deleted file mode 100644 index 639e7be49..000000000 Binary files a/server/images/android_screenshot@2x.png and /dev/null differ diff --git a/server/images/ios_screenshot.png b/server/images/ios_screenshot.png deleted file mode 100644 index 03c51fab7..000000000 Binary files a/server/images/ios_screenshot.png and /dev/null differ diff --git a/server/images/ios_screenshot@2x.png b/server/images/ios_screenshot@2x.png deleted file mode 100644 index 8499acfe5..000000000 Binary files a/server/images/ios_screenshot@2x.png and /dev/null differ diff --git a/web/splash/splash.css b/web/splash/splash.css index 073554a0a..eaa5669ef 100644 --- a/web/splash/splash.css +++ b/web/splash/splash.css @@ -1,222 +1,217 @@ div.headerContainer { flex: 1 1 auto; background-image: url(../images/background.png); background-size: 3000px 2000px; background-attachment: fixed; padding: 0 10px; } div.topContainer { position: absolute; top: 0; left: 0; right: 0; } div.content { flex: 1 0 0; position: relative; min-height: 100%; } div.top { max-width: 1024px; margin: 0 auto; } div.headerContents { display: flex; justify-content: space-between; align-items: center; padding-top: 5px; padding-bottom: 7px; } div.actionLinks > * { padding-right: 15px; color: white; font-weight: 300; } div.actionLinks > *:last-child { padding-right: 0; } header.header h1 { color: white; font-size: 38px; } header.header span.requestAccess { padding: 10px 20px; border-radius: 20px; border: 1px solid white; } div.body { padding: 30px 0 20px 0; } div.intro { text-align: center; margin-bottom: 50px; } p.introHeader { color: white; font-size: 28px; font-weight: 300; } p.introDescription { color: white; font-size: 21px; font-weight: 300; padding-top: 5px; } -div.devices { - display: flex; - justify-content: space-between; - margin: 0 159px; -} div.bottomContainer { z-index: 2; position: relative; overflow: auto; height: 100%; } div.bottom { margin-top: 728px; background-image: url(../images/background.png); background-size: 3000px 2000px; background-attachment: fixed; min-height: 100%; display: flex; flex-direction: column; } div.headerRest { background-color: rgba(255, 255, 255, 0.84); flex-grow: 1; } div.headerOverscroll { position: fixed; top: 100%; left: 0; right: 0; height: 1000px; background-color: white; } div.prompt { margin: 0 auto; display: flex; flex-direction: column; align-items: center; } p.promptHeader { color: #282828; font-size: 21px; padding-top: 25px; text-align: center; } p.promptDescription { color: #282828; font-size: 18px; padding-top: 9px; text-align: center; } div.requestAccessContainer { margin: 25px; display: flex; flex-direction: column; align-items: center; } form.requestAccessForm { display: flex; align-items: center; } input.requestAccessEmail { width: 300px; border: 0; padding: 10px 10px 8px 10px; font-size: 18px; border-radius: 5px; background-color: rgba(119, 119, 119, 0.13); color: black; } input.requestAccessEmail::placeholder, input.requestAccessEmail::-ms-input-placeholder { color: #777777; } button.requestAccessSubmit { border: 0px; padding: 10px 10px 8px 10px; font-size: 18px; border-radius: 5px; background-color: rgba(0, 170, 0, 0.53); color: white; margin-left: 15px; cursor: pointer; width: 78px; height: 39px; } p.androidWarning { font-size: 14px; padding: 5px; } p.requestAccessError { font-size: 14px; padding: 10px; text-align: center; color: red; } p.requestAccessSuccess { font-size: 18px; padding: 20px; text-align: center; } div.customSelect { position: relative; display: block; border: 1px solid #bbb; border-radius: 0.3em; background-color: #f5f5f5; margin-left: 15px; } div.customSelect::after { content: ' '; position: absolute; top: 50%; right: 1em; z-index: 2; pointer-events: none; display: none; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 7px solid #666; margin-top: -3px; } div.customSelect select { width: 100%; margin: 0; outline: none; padding: 0.6em 0.8em 0.5em 0.8em; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; font-size: 16px; font-family: sans-serif; color: #444; border-radius: 0.2em; } div.customSelect select:focus { color: #222; outline: none; } @supports (-webkit-appearance: none) or (appearance: none) or ((-moz-appearance: none) and (mask-type: alpha)) { div.customSelect::after { display: block; } div.customSelect select { padding-right: 2em; background: none; border: 1px solid transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } div.customSelect select:focus { border-color: #aaa; } } diff --git a/web/splash/splash.react.js b/web/splash/splash.react.js index 98de90329..350a57fbc 100644 --- a/web/splash/splash.react.js +++ b/web/splash/splash.react.js @@ -1,283 +1,269 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { requestAccessActionTypes, requestAccess, } from 'lib/actions/user-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { validEmailRegex } from 'lib/shared/account-utils'; import type { AccessRequest } from 'lib/types/account-types'; import { type DeviceType, assertDeviceType } from 'lib/types/device-types'; import { type LoadingStatus } from 'lib/types/loading-types'; import { type DispatchActionPromise, useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils'; import Button from '../components/button.react'; import LoadingIndicator from '../loading-indicator.react'; import LogInModal from '../modals/account/log-in-modal.react'; import { useModalContext } from '../modals/modal-provider.react'; import { useSelector } from '../redux/redux-utils'; import css from './splash.css'; const defaultRequestAccessScrollHeight = 390; type Props = { +loadingStatus: LoadingStatus, +dispatchActionPromise: DispatchActionPromise, +requestAccess: (accessRequest: AccessRequest) => Promise, +setModal: (modal: React.Node) => void, +modal: ?React.Node, }; type State = { +platform: DeviceType, +email: string, +error: ?string, +success: ?string, }; class Splash extends React.PureComponent { emailInput: ?HTMLInputElement; bottomContainer: ?HTMLDivElement; state: State = { platform: 'ios', email: '', error: null, success: null, }; componentDidMount() { if ('scrollRestoration' in history) { history.scrollRestoration = 'manual'; } } render() { let androidWarning = null; if (this.state.platform === 'android') { androidWarning = (

Make sure this is the email you use to log in to the Google Play Store!

); } let error = null; if (this.state.error) { error =

{this.state.error}

; } let success = null; if (this.state.success) { success = (

{this.state.success}

); } let submitButtonContent = 'Submit'; if (this.props.loadingStatus === 'loading') { submitButtonContent = ( ); } return (

Comm is a chat app with an integrated calendar.

We make it incredibly easy to plan events with your friends.

-
- - -

We're currently alpha testing the first version of our app.

If you'd like to try it out, please let us know!

{androidWarning}
{error} {success}
{this.props.modal} ); } bottomContainerRef = (bottomContainer: ?HTMLDivElement) => { this.bottomContainer = bottomContainer; }; emailInputRef = (emailInput: ?HTMLInputElement) => { this.emailInput = emailInput; }; onChangeEmail = (event: SyntheticEvent) => { this.setState({ email: event.currentTarget.value }); }; onChangePlatform = (event: SyntheticEvent) => { this.setState({ platform: assertDeviceType(event.currentTarget.value) }); }; onClickLogIn = (event: SyntheticEvent) => { event.preventDefault(); this.props.setModal(); }; onClickRequestAccess = (event: SyntheticEvent) => { event.preventDefault(); const { bottomContainer } = this; invariant(bottomContainer, 'bottomContainer should exist'); const formHeight = 180; const contentHeight = 790; const guaranteesSpace = contentHeight - window.innerHeight + formHeight; if (bottomContainer.scrollTop < guaranteesSpace) { bottomContainer.scrollTop = Math.max( defaultRequestAccessScrollHeight, guaranteesSpace, ); } if (this.emailInput) { this.emailInput.focus(); } }; onSubmitRequestAccess = (event: SyntheticEvent) => { event.preventDefault(); if (this.state.email.search(validEmailRegex) === -1) { this.setState({ success: null, error: 'Please enter a valid email!' }); invariant(this.emailInput, 'should be set'); this.emailInput.focus(); return; } this.props.dispatchActionPromise( requestAccessActionTypes, this.requestAccessAction(), ); }; async requestAccessAction() { try { await this.props.requestAccess({ email: this.state.email, platform: this.state.platform, }); this.setState({ success: "Thanks for your interest! We'll let you know as soon as " + "we're able to extend an invite.", error: null, }); } catch (e) { this.setState({ success: null, error: 'Unknown error...' }); throw e; } } } const loadingStatusSelector = createLoadingStatusSelector( requestAccessActionTypes, ); const ConnectedSplash: React.ComponentType<{}> = React.memo<{}>( function ConnectedSplash(): React.Node { const loadingStatus = useSelector(loadingStatusSelector); const callRequestAccess = useServerCall(requestAccess); const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); return ( ); }, ); export default ConnectedSplash;