v1.6.4/tutorial complete

This commit is contained in:
2020-08-26 23:28:07 -04:00
parent 60758dc35a
commit 14c90d4cb9
6 changed files with 400 additions and 12 deletions
+16 -1
View File
@@ -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}
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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 &amp; 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>
);
}
+32
View File
@@ -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;
}