v1.6.4/tutorial complete
This commit is contained in:
+16
-1
@@ -23,6 +23,7 @@ import {
|
||||
PLAYER_SOURCE,
|
||||
getShowWPButton,
|
||||
getTutorialStatus,
|
||||
setTutorialStatus,
|
||||
} from './Api';
|
||||
import Tutorial from './Tutorial';
|
||||
|
||||
@@ -74,6 +75,8 @@ const startResize = (ev) => {
|
||||
const App = () => {
|
||||
const closedNotification = { open: false, message: '' };
|
||||
|
||||
const [tutorialComponent, setTutorialComponent] = useState(null);
|
||||
const [showFab, setShowFab] = useState(false);
|
||||
const [tutorialComplete, setTutorialComplete] = useState(false);
|
||||
const [status, setStatus] = useState({ active: false, message: '' });
|
||||
const [visible, setVisible] = useState(false);
|
||||
@@ -94,6 +97,7 @@ const App = () => {
|
||||
setLoading(false);
|
||||
});
|
||||
getShowWPButton().then((showWPButton) => {
|
||||
setShowFab(showWPButton);
|
||||
if (showWPButton === true) {
|
||||
document.querySelector('.watch-party-fab').classList.remove('watch-party-fab-hidden');
|
||||
}
|
||||
@@ -134,6 +138,11 @@ const App = () => {
|
||||
if (document.fullscreenElement) setVisible(false);
|
||||
};
|
||||
|
||||
const resetTutorial = (c = null) => {
|
||||
setTutorialComponent(c);
|
||||
setTutorialComplete(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<Snackbar
|
||||
@@ -145,8 +154,11 @@ const App = () => {
|
||||
autoHideDuration={6000}
|
||||
/>
|
||||
<Tutorial
|
||||
setTutorialCompleteState={setTutorialComplete}
|
||||
resetTutorial={resetTutorial}
|
||||
tutorialComplete={tutorialComplete}
|
||||
showFab={showFab}
|
||||
visible={visible}
|
||||
tutorialComponent={tutorialComponent}
|
||||
/>
|
||||
<div className="party-content-wrapper">
|
||||
<div id="party-routes-wrapper">
|
||||
@@ -162,6 +174,9 @@ const App = () => {
|
||||
{loading && <Loading />}
|
||||
{status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? (
|
||||
<Routes
|
||||
showFab={showFab}
|
||||
resetTutorial={resetTutorial}
|
||||
tutorialComplete={tutorialComplete}
|
||||
updateLoading={setLoading}
|
||||
notify={(message) => setNotification({ open: true, message })}
|
||||
appVersion={APP_VERSION}
|
||||
|
||||
@@ -175,6 +175,11 @@ export default class Chat extends Component {
|
||||
this.props.notify('Uh oh. Got lost from the party.');
|
||||
goTo(Create, this.props);
|
||||
return;
|
||||
} else {
|
||||
// CONTINUE TUTORIAL
|
||||
if (this.props.tutorialComplete === false) {
|
||||
this.props.resetTutorial('chat');
|
||||
}
|
||||
}
|
||||
|
||||
if (response.messages) {
|
||||
|
||||
+34
-4
@@ -37,6 +37,7 @@ import {
|
||||
updateLocalData,
|
||||
getUserUid,
|
||||
emptyLocalData,
|
||||
setTutorialStatus,
|
||||
} from './Api';
|
||||
import { goTo } from 'route-lite';
|
||||
import Chat from './Chat';
|
||||
@@ -90,7 +91,18 @@ export default class Create extends Component {
|
||||
}
|
||||
componentDidMount() {
|
||||
const { lastActive, userName, partyName, partyPin, allowAutoRejoin } = LocalData();
|
||||
if (allowAutoRejoin === true && lastActive && userName && partyName && partyPin) {
|
||||
// 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);
|
||||
@@ -262,7 +274,7 @@ export default class Create extends Component {
|
||||
alertStep,
|
||||
expanded,
|
||||
} = this.state;
|
||||
const { status } = this.props;
|
||||
const { status, resetTutorial } = this.props;
|
||||
return (
|
||||
<div className="party-create-container">
|
||||
<Typography
|
||||
@@ -373,7 +385,10 @@ export default class Create extends Component {
|
||||
<span>{mode === 'create' ? 'Start Party' : 'Join Party'}</span> <ChevronRight />
|
||||
</Button>
|
||||
</Paper>
|
||||
<ExpansionPanel expanded={expanded === 'alerts'} className="create-settings-card">
|
||||
<ExpansionPanel
|
||||
expanded={expanded === 'alerts'}
|
||||
className="create-settings-card create-alerts-card"
|
||||
>
|
||||
<ExpansionPanelSummary
|
||||
onClick={() => this.handleExpanders('alerts')}
|
||||
expandIcon={<ExpandLess />}
|
||||
@@ -431,7 +446,10 @@ export default class Create extends Component {
|
||||
)}
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
<ExpansionPanel expanded={expanded === 'settings'} className="create-settings-card">
|
||||
<ExpansionPanel
|
||||
expanded={expanded === 'settings'}
|
||||
className="create-settings-card create-settings-expander"
|
||||
>
|
||||
<ExpansionPanelSummary
|
||||
onClick={() => this.handleExpanders('settings')}
|
||||
expandIcon={<ExpandLess />}
|
||||
@@ -482,6 +500,18 @@ export default class Create extends Component {
|
||||
}
|
||||
labelPlacement="end"
|
||||
/>
|
||||
<Button
|
||||
color="secondary"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setTutorialStatus(false);
|
||||
resetTutorial();
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
START TUTORIAL
|
||||
</Button>
|
||||
<Button
|
||||
color="secondary"
|
||||
fullWidth
|
||||
|
||||
+250
-5
@@ -1,22 +1,267 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Popover } from '@material-ui/core';
|
||||
import { Popover, MobileStepper, Button, Typography } from '@material-ui/core';
|
||||
import { setTutorialStatus } from './Api';
|
||||
|
||||
export default class Tutorial extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
open: !props.tutorialComplete,
|
||||
open: false,
|
||||
el: null,
|
||||
index: 0,
|
||||
};
|
||||
this.getAnchorEl = this.getAnchorEl.bind(this);
|
||||
this.nextOrBack = this.nextOrBack.bind(this);
|
||||
this.steps = [
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Take A Tour</Typography>
|
||||
<Typography variant="body2">
|
||||
Welcome to Watch Party! Take a quick tour to see how it works. Start by clicking on
|
||||
the (WP) button to the right...
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.watch-party-fab',
|
||||
dn: () => this.props.visible !== true,
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Create / Join</Typography>
|
||||
<Typography variant="body2">
|
||||
This is the home screen, you can create or join a party from here.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.create-input-card',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Resize</Typography>
|
||||
<Typography variant="body2">
|
||||
Use this little tab <span id="resize-demo">👉</span> to resize the sidebar, double
|
||||
click on it to resize to the default width
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '#party-width-dragger',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Notifications</Typography>
|
||||
<Typography variant="body2">
|
||||
Keep an eye on this section for any important notifications, use the left and right
|
||||
buttons to see more notifications
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.create-alerts-card',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Settings</Typography>
|
||||
<Typography variant="body2">
|
||||
Click on 'Settings' to see your available options. You can start the tour again from
|
||||
here if needed.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.create-settings-expander',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Create A Party</Typography>
|
||||
<Typography variant="body2">
|
||||
Alright, now fill out the fields here, and create a party. We'll continue the tour
|
||||
after you're in a party.
|
||||
<br />
|
||||
Click on next to be able to type.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.create-input-card',
|
||||
on: () => this.setState({ open: false }),
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Title Card</Typography>
|
||||
<Typography variant="body2">
|
||||
This top area is the 'Title Card', click on or near the down arrow to see your
|
||||
settings, and other details. If you're on a call you can control the volume from here.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
db: () => true,
|
||||
e: '.party-chat-header',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Now Playing</Typography>
|
||||
<Typography variant="body2">
|
||||
Start playing something and you will see this area update to show what's currently
|
||||
playing.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.media-info-card',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Chat & Call</Typography>
|
||||
<Typography variant="body2">
|
||||
You can send messages, start/join a call, or go fullscreen from here. You can send a
|
||||
gif, by click on the GIF button.
|
||||
<br />
|
||||
Use this fullscreen button to have access to Watch Party when in fullscreen.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.text-phone-panel',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Hide Sidebar</Typography>
|
||||
<Typography variant="body2">
|
||||
You can hide the sidebar by click on the (WP) button again, sync will continue to work
|
||||
even when hidden.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '.watch-party-fab',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">Hide Watch Party</Typography>
|
||||
<Typography variant="body2">
|
||||
Look for the Watch Party icon in your extensions bar, you can hide the (WP) button
|
||||
from your screen when you don't want it in your way.
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e:
|
||||
'div.party-chat-header div.MuiButtonBase-root.MuiIconButton-root.MuiExpansionPanelSummary-expandIcon.MuiIconButton-edgeEnd',
|
||||
},
|
||||
{
|
||||
c: (
|
||||
<div className="tutorial-content">
|
||||
<Typography variant="subtitle1">ALL DONE</Typography>
|
||||
<Typography variant="body2">
|
||||
That's it! Go enjoy your favorite show with your favorite people!
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
e: '#party-width-dragger',
|
||||
},
|
||||
];
|
||||
}
|
||||
componentDidMount() {
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
open: !this.props.tutorialComplete && this.props.showFab,
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
getAnchorEl() {
|
||||
const { index } = this.state;
|
||||
return document.querySelector(this.steps[index].e);
|
||||
}
|
||||
nextOrBack(v) {
|
||||
const { index } = this.state;
|
||||
if (this.steps[index].on) this.steps[index].on();
|
||||
if (v > 0) {
|
||||
if (index < this.steps.length - 1) this.setState({ index: index + 1 });
|
||||
else {
|
||||
this.setState({ open: false });
|
||||
setTutorialStatus(true);
|
||||
}
|
||||
} else if (v < 0) {
|
||||
if (index > 0) this.setState({ index: index - 1 });
|
||||
else if (index === 0) {
|
||||
this.setState({ open: false });
|
||||
setTutorialStatus(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
open: !nextProps.tutorialComplete && nextProps.showFab,
|
||||
});
|
||||
if (nextProps.tutorialComponent === 'chat') {
|
||||
this.setState({
|
||||
index: 6,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
index: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { open } = this.state;
|
||||
const { open, index, el } = this.state;
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
el: this.getAnchorEl(),
|
||||
});
|
||||
}, 1000);
|
||||
return (
|
||||
<Popover
|
||||
hideBackdrop
|
||||
className="watch-party-tutorial"
|
||||
anchorEl={document.querySelector('.watch-party-fab')}
|
||||
anchorEl={el}
|
||||
open={open}
|
||||
anchorOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'center',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
>
|
||||
TUTORIAL START
|
||||
{this.steps[index].c}
|
||||
<MobileStepper
|
||||
className="tutorial-stepper"
|
||||
position="static"
|
||||
steps={this.steps.length}
|
||||
activeStep={index}
|
||||
variant="progress"
|
||||
LinearProgressProps={{
|
||||
color: 'secondary',
|
||||
}}
|
||||
backButton={
|
||||
<Button
|
||||
onClick={() => this.nextOrBack(-1)}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
disabled={this.steps[index].db && this.steps[index].db()}
|
||||
>
|
||||
{index === 0 ? 'Skip' : 'Back'}
|
||||
</Button>
|
||||
}
|
||||
nextButton={
|
||||
<Button
|
||||
onClick={() => this.nextOrBack(1)}
|
||||
size="small"
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
disabled={this.steps[index].dn && this.steps[index].dn()}
|
||||
>
|
||||
{index === this.steps.length - 1 ? 'Done' : 'Next'}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ body {
|
||||
margin: 0 !important;
|
||||
background-color: black;
|
||||
transition: max-width ease-in-out 0.35s;
|
||||
overflow-y: initial !important;
|
||||
}
|
||||
body.local {
|
||||
background-color: white;
|
||||
@@ -910,7 +911,38 @@ button.giphy-list-item {
|
||||
|
||||
.watch-party-tutorial {
|
||||
z-index: 9999 !important;
|
||||
height: 0;
|
||||
}
|
||||
.watch-party-tutorial .MuiPaper-root.MuiPopover-paper {
|
||||
padding: 20px;
|
||||
max-width: 400px;
|
||||
max-height: none;
|
||||
}
|
||||
.tutorial-stepper {
|
||||
position: relative !important;
|
||||
min-width: 400px !important;
|
||||
background: none !important;
|
||||
}
|
||||
.tutorial-content {
|
||||
padding: 15px 10px;
|
||||
}
|
||||
.tutorial-content h6 {
|
||||
font-size: 14px;
|
||||
color: #c0f300;
|
||||
letter-spacing: 2.5px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.tutorial-content p {
|
||||
font-size: 12px;
|
||||
}
|
||||
#resize-demo {
|
||||
padding: 10px;
|
||||
border-radius: 20px;
|
||||
background: #2c2c2c;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user