/************************************************************************ 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 , 2020 https://www.chromewatchparty.com/copyright ========================================================================= ALL CONTENT ON WATCH PARTY'S WEBSITE OR IN WATCH PARTY'S CHROME EXTENSION APP, UNLESS OTHERWISE CITED ARE THE SOLE INTELLECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION. ************************************************************************/ /*global chrome */ import React, { Component } from "react"; import { Button, FormControlLabel, Switch, TextField, Typography, Paper, ButtonGroup, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, MobileStepper, IconButton, Card, CardContent, CardActions, } from "@material-ui/core"; import { JoinRoomApi, CreateRoomApi, PLAYER_STATUS, getPlayerSource, LocalData, updateLocalData, getUserUid, emptyLocalData, setTutorialStatus, } from "./Api"; import { goTo } from "route-lite"; import Chat from "./Chat"; import { ChevronRight, InfoRounded, MonetizationOnRounded, RateReviewRounded, Settings, ExpandLess, KeyboardArrowLeft, KeyboardArrowRight, Notifications, } 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, publicParty: false, alertStep: this.props.status && this.props.status.importantAlert ? this.props.status.importantAlert : 0, allowAutoRejoin: LocalData().allowAutoRejoin !== undefined ? LocalData().allowAutoRejoin : true, allowChatNotification: LocalData().allowChatNotification !== undefined ? LocalData().allowChatNotification : true, allowAutoFollow: LocalData().allowAutoFollow || false, expanded: "alerts", }; this.createCall = this.createCall.bind(this); this.joinCall = this.joinCall.bind(this); this.success = this.success.bind(this); this.partyNameAutocompleteProcessor = this.partyNameAutocompleteProcessor.bind( this ); this.updateAllowAutoRejoin = this.updateAllowAutoRejoin.bind(this); this.updateAllowAutoFollow = this.updateAllowAutoFollow.bind(this); this.updateAllowChatNotification = this.updateAllowChatNotification.bind( this ); this.clearPartyHistory = this.clearPartyHistory.bind(this); this.handleSteps = this.handleSteps.bind(this); } componentDidMount() { const { lastActive, userName, partyName, partyPin, allowAutoRejoin, } = LocalData(); // CONTINUE TUTORIAL if (this.props.tutorialComplete === false) { this.props.resetTutorial(); } if ( this.props.showFab === true && allowAutoRejoin === true && lastActive && userName && partyName && partyPin ) { if ( Math.abs(new Date(parseInt(lastActive)) - new Date().getTime()) <= 60000 ) { this.props.updateLoading(true); this.props.setVisible(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 || this.state.publicParty, publicParty: this.state.publicParty, }; 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) => { emptyLocalData(); 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); } } updateAllowChatNotification() { updateLocalData({ allowChatNotification: !this.state.allowChatNotification, }); this.setState({ allowChatNotification: !this.state.allowChatNotification }); } updateAllowAutoRejoin() { updateLocalData({ allowAutoRejoin: !this.state.allowAutoRejoin }); this.setState({ allowAutoRejoin: !this.state.allowAutoRejoin }); } updateAllowAutoFollow() { updateLocalData({ allowAutoFollow: !this.state.allowAutoFollow }); this.setState({ allowAutoFollow: !this.state.allowAutoFollow }); } clearPartyHistory() { this.setState({ parties: [], }); chrome.runtime.sendMessage({ type: "EMPTY_PARTIES" }); } handleSteps(direction) { const { alertStep } = this.state; if (alertStep + direction < 0) return; if (alertStep + direction >= this.props.status.alerts.length) return; this.setState({ alertStep: alertStep + direction }); } handleExpanders(e) { const { expanded } = this.state; if (e === expanded) this.setState({ expanded: "" }); else this.setState({ expanded: e }); } render() { const { mode, name, pin, userName, parties, adminOnly, publicParty, allowAutoRejoin, allowAutoFollow, allowChatNotification, alertStep, expanded, } = this.state; const { status, resetTutorial } = this.props; return (
WATCH PARTY this.userNameChange(e.target.value)} helperText={ userName ? `${userName.length}/${CONSTANTS.USER_NAME_LENGTH} Characters` : null } /> 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) => ( )} /> this.partyPinChange(e.target.value)} helperText={ pin ? `${pin.length}/${CONSTANTS.PIN_LENGTH} Digits` : null } /> this.setState({ adminOnly: !adminOnly })} name="adminOnly" color={adminOnly || publicParty ? "secondary" : "primary"} /> } label={ Admin Only Mode (can be changed later)
{adminOnly || publicParty ? "Only admin will update currently playing and start calls" : "All members will update currently playing and start calls"}
} labelPlacement="end" /> {/* this.setState({ publicParty: !publicParty })} name="publicParty" color={publicParty ? "secondary" : "primary"} /> } label={ Public Party (can be changed later)
{publicParty ? "Party will be listed and available to join from Watch Party website" : "Only people you share with can join"}
} labelPlacement="end" /> */}
this.handleExpanders("alerts")} expandIcon={} > Alerts {status ? (
{status.alerts[alertStep].title} {status.alerts[alertStep].description} {status.alerts[alertStep].link && status.alerts[alertStep].linkText && ( )} this.handleSteps(-1)} > } nextButton={ this.handleSteps(1)} > } steps={status.alerts ? status.alerts.length : 0} />
) : ( No alerts right now )}
this.handleExpanders("settings")} expandIcon={} > Settings } label={ Allow chat notification when side panel is closed
{allowChatNotification ? "Notifications Enabled" : "Notifications Disabled"}
} labelPlacement="end" /> } label={ Allow Watch Party to auto rejoin (within 1 minute)
{allowAutoRejoin ? "Auto Rejoin Enabled" : "Auto Rejoin Disabled"}
} labelPlacement="end" /> } label={ Allow Watch Party to change to the currently playing show
{allowAutoFollow ? "Auto Follow Enabled" : "Auto Follow Disabled"}
} labelPlacement="end" />
); } }