Files
watchparty/app/src/Create.js
T

351 lines
12 KiB
JavaScript

/************************************************************************
Copyright (C) Ayushya Amitabh - All Rights Reserved
Unauthorized copying of this file, via any medium is strictly prohibited
Proprietary and confidential
Written by Ayushya Amitabh <admin@chromewatchparty.com>, 2020
https://www.chromewatchparty.com/copyright
=========================================================================
ALL CONTENT ON IN WATCH PARTY'S CHROME EXTENSION APP, UNLESS OTHERWISE
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
Netflix logo is a trademark and intellectual property of Netflix, Inc.
Disney+ logo is a trademark and intellectual property of The Walt Disney Company
Prime logo is a trademark and intellectual property of Amazon.com, Inc.
YouTube logo is a trademark and intellectual property of Google, Inc.
Hulu logo is a trademark and intellectual property of Hulu, LLC.
HBO Now and HBO Max logos are trademark and intellectual property of WarnerMedia Direct,LLC.
************************************************************************/
/*global chrome */
import React, { Component } from 'react';
import { Button, FormControlLabel, Switch, TextField, Typography, Paper, ButtonGroup } from '@material-ui/core';
import {
JoinRoomApi,
CreateRoomApi,
PLAYER_STATUS,
getPlayerSource,
LocalData,
updateLocalData,
getUserUid,
} from './Api';
import { goTo } from 'route-lite';
import Chat from './Chat';
import {
ChevronRight,
InfoRounded,
MonetizationOnRounded,
RateReviewRounded,
} from '@material-ui/icons';
import { Autocomplete } from "@material-ui/lab";
const CONSTANTS = {
USER_NAME_LENGTH: 12,
NAME_LENGTH: 24,
PIN_LENGTH: 9,
};
export default class Create extends Component {
constructor(props) {
super(props);
const defaultMode = LocalData().partyName ? 'join' : 'create';
this.state = {
userName: LocalData().userName || '',
name: LocalData().partyName || '',
pin: LocalData().partyPin || '',
mode: defaultMode,
parties: [],
adminOnly: false,
};
this.createCall = this.createCall.bind(this);
this.joinCall = this.joinCall.bind(this);
this.success = this.success.bind(this);
this.partyNameAutocompleteProcessor = this.partyNameAutocompleteProcessor.bind(this);
}
componentDidMount() {
const { lastActive, userName, partyName, partyPin, allowAutoRejoin } = LocalData();
if (allowAutoRejoin === true && lastActive && userName && partyName && partyPin) {
if (Math.abs(new Date(parseInt(lastActive)) - new Date().getTime()) <= 60000) {
this.props.updateLoading(true);
this.joinCall(userName, partyName, partyPin);
}
}
chrome.runtime.sendMessage(
{
type: 'GET_PARTIES'
},
(response) => {
this.setState({ parties: response });
}
);
}
partyNameChange(value) {
if (value.length <= CONSTANTS.NAME_LENGTH) this.setState({ name: value });
}
partyPinChange(value) {
if (value.length <= CONSTANTS.PIN_LENGTH) this.setState({ pin: value });
}
userNameChange(value) {
if (value.length <= CONSTANTS.USER_NAME_LENGTH) this.setState({ userName: value });
}
createOrJoin() {
this.props.updateLoading(true);
getUserUid();
const { userName, name, pin, mode } = this.state;
if (!userName.replace(/\s+/g, '')) {
this.props.notify('Missing user name');
this.props.updateLoading(false);
return;
}
if (!name.replace(/\s+/g, '')) {
this.props.notify('Missing party name');
this.props.updateLoading(false);
return;
}
if (!pin.replace(/\s+/g, '')) {
this.props.notify('Missing party pin');
this.props.updateLoading(false);
return;
}
if (userName && name && pin) {
switch (mode) {
case 'create':
this.createCall(userName.trim(), name.trim(), pin);
break;
case 'join':
this.joinCall(userName.trim(), name.trim(), pin);
break;
default:
this.props.updateLoading(false);
break;
}
} else {
this.props.notify('Double check your inputs');
}
}
createCall(userName, partyName, partyPin) {
this.props.updateLoading(true);
getUserUid();
const apidata = {
userName,
partyName,
partyPin,
player: {
source: getPlayerSource(),
status: PLAYER_STATUS.PAUSED,
time: 0,
url: window.location.href,
},
adminOnly: this.state.adminOnly,
};
CreateRoomApi(apidata)
.then((res) => res.json())
.then((createResult) => {
if (createResult.status <= 299) {
this.success(userName, partyName, partyPin);
} else {
this.props.updateLoading(false);
this.props.notify(createResult.message || createResult.statusText);
}
})
.catch((err) => {
console.error('Create Party API Error', err);
this.props.notify(err.message || 'Something went wrong');
this.props.updateLoading(false);
});
}
joinCall(userName, partyName, partyPin) {
const apidata = {
userName,
partyName,
partyPin,
source: getPlayerSource(),
};
getUserUid();
JoinRoomApi(apidata)
.then((res) => res.json())
.then((joinResult) => {
if (joinResult.status <= 299) {
this.success(userName, partyName, partyPin);
} else {
this.props.updateLoading(false);
this.props.notify(joinResult.message || joinResult.statusText);
}
})
.catch((err) => {
console.error('Join Party API Error', err);
this.props.notify(err.message || 'Something went wrong');
this.props.updateLoading(false);
});
}
success(userName, partyName, partyPin) {
updateLocalData({ userName, partyName, partyPin });
this.props.updateLoading(false);
goTo(Chat, this.props);
}
partyNameAutocompleteProcessor(v) {
if (v !== null && v !== undefined && typeof (v) === 'object') {
if (v.name) this.partyNameChange(v.name);
else this.partyNameChange('');
if (v.pin) this.partyPinChange(v.pin);
else this.partyPinChange('');
} else if (typeof (v) === 'object' && (v === null || v === undefined)) {
this.partyNameChange('');
this.partyPinChange('');
} else if (v !== undefined && v !== null && typeof (v) === 'string') {
this.partyNameChange(v);
}
}
render() {
const { mode, name, pin, userName, parties, adminOnly } = this.state;
return (
<div className="party-create-container">
<Typography
color="secondary"
className="brand-title"
variant="h6"
display="block"
gutterBottom
>
WATCH PARTY
</Typography>
<Paper className="create-input-card" elevation={3}>
<ButtonGroup className="create-mode-select" size="small" fullWidth>
<Button
id="mode-select-left"
variant={mode === 'create' ? 'contained' : null}
color={mode === 'create' ? 'secondary' : null}
disableElevation={mode === 'create'}
onClick={() => this.setState({ mode: 'create' })}
>
Create
</Button>
<Button
id="mode-select-right"
variant={mode === 'join' ? 'contained' : null}
color={mode === 'join' ? 'secondary' : null}
disableElevation={mode === 'join'}
onClick={() => this.setState({ mode: 'join' })}
>
Join
</Button>
</ButtonGroup>
<TextField
color="secondary"
size="small"
className="create-name addFocus"
label="Name"
variant="outlined"
value={userName}
onChange={(e) => this.userNameChange(e.target.value)}
helperText={
userName ? `${userName.length}/${CONSTANTS.USER_NAME_LENGTH} Characters` : null
}
/>
<Autocomplete
color="secondary"
options={parties}
getOptionLabel={o => o.name}
autoComplete
freeSolo
value={{name:name, pin: pin}}
onInputChange={(e,v,r) => this.partyNameAutocompleteProcessor({name: v, pin: pin})}
onChange={(e, v) => this.partyNameAutocompleteProcessor(v)}
renderInput={(params) =>
<TextField
color="secondary"
size="small"
{...params}
className="create-name addFocus"
label="Party Name"
variant="outlined"
helperText={name ? `${name.length}/${CONSTANTS.NAME_LENGTH} Characters` : null}
/>}
/>
<TextField
color="secondary"
size="small"
className="create-pin addFocus"
label="Party Pin"
variant="outlined"
type="number"
value={pin}
onChange={(e) => this.partyPinChange(e.target.value)}
helperText={pin ? `${pin.length}/${CONSTANTS.PIN_LENGTH} Digits` : null}
/>
{
mode === 'create' ?
<FormControlLabel
className="notification-switch admin-only-switch"
control={
<Switch
checked={adminOnly}
onChange={() => this.setState({ adminOnly: !adminOnly })}
name="adminOnly"
color={adminOnly ? 'secondary' : 'primary'}
/>
}
label={
<span>
Admin Only Mode (can be changed later)
<br />
<span style={{ color: '#8a8a8a' }}>
{adminOnly ? 'Only admin will update currently playing' : 'All members will update currently playing'}
</span>
</span>
}
labelPlacement="end"
/> : null
}
<Button
size="small"
variant="contained"
color="secondary"
onClick={() => this.createOrJoin()}
>
<span>{mode === 'create' ? 'Start Party' : 'Join Party'}</span> <ChevronRight />
</Button>
</Paper>
<Button
target="_blank"
href={`http://www.chromewatchparty.com/changes/v${this.props.appVersion}`}
fullWidth
color="secondary"
variant="outlined"
size="large"
className="whats-new-button"
>
See what's new in V{this.props.appVersion}
</Button>
<div className="create-bottom-card">
<Button
color="secondary"
target="_blank"
startIcon={<InfoRounded />}
size="small"
href="https://www.chromewatchparty.com/welcome/#tips"
>
FAQ
</Button>
<Button
color="secondary"
target="_blank"
startIcon={<RateReviewRounded />}
size="small"
href="https://get.chromewatchparty.com"
>
Review
</Button>
<Button
color="secondary"
target="_blank"
startIcon={<MonetizationOnRounded />}
size="small"
href="https://paypal.me/Ayushya"
>
Donate
</Button>
</div>
</div>
);
}
}