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
+63 -2
View File
@@ -46,19 +46,26 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
padding: 15px; padding: 15px;
} }
#clear-button { #clear-button {
width: max-content; font-size: 10px;
letter-spacing: 2px;
} }
.mdc-switch { .mdc-switch {
--mdc-theme-secondary: #c0f300 !important; --mdc-theme-secondary: #c0f300 !important;
--mdc-theme-surface: #ffffff !important; --mdc-theme-surface: #ffffff !important;
margin: 10px 5px; margin: 10px 5px;
} }
.label-container > * {
width: 100%;
text-align: center;
display: block;
}
label { label {
color: var(--mdc-theme-text-primary-on-dark); color: var(--mdc-theme-text-primary-on-dark);
text-transform: uppercase; text-transform: uppercase;
} }
.switch-container { .switch-container {
margin: 20px 0; margin: 20px 0;
min-width: max-content;
} }
.switch-wrapper { .switch-wrapper {
display: flex; display: flex;
@@ -73,6 +80,27 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
.switch-wrapper .label-container span { .switch-wrapper .label-container span {
color: var(--mdc-theme-text-hint-on-dark); color: var(--mdc-theme-text-hint-on-dark);
} }
a.mdc-button {
font-size: 10px;
display: inline-flex;
flex: 1;
width: auto;
}
#divider {
height: 1px;
background: #555555;
position: relative;
margin: 15px 0;
}
#divider::before {
content: attr(data-title);
color: white;
top: -8px;
position: absolute;
background-color: #2c2c2c;
padding-right: 10px;
}
</style> </style>
<link <link
href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css"
@@ -83,6 +111,30 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
</head> </head>
<body> <body>
<script src="popup.js"></script> <script src="popup.js"></script>
<h5
style="
margin: 0;
color: var(--mdc-theme-text-primary-on-dark);
letter-spacing: 3px;
font-size: 14px;
font-weight: 400;
margin-bottom: 10px;
"
>
WATCH PARTY
</h5>
<p
style="
margin-top: 0;
margin-bottom: 25px !important;
display: block;
color: var(--mdc-theme-on-error);
"
>
To use Watch Party, head on over to any supported website.
</p>
<div data-title="LINKS" id="divider"></div>
<a class="mdc-button" target="_blank" href="https://www.chromewatchparty.com/welcome"> <a class="mdc-button" target="_blank" href="https://www.chromewatchparty.com/welcome">
<div class="mdc-button__ripple"></div> <div class="mdc-button__ripple"></div>
<i class="material-icons mdc-button__icon" aria-hidden="true">school</i> <i class="material-icons mdc-button__icon" aria-hidden="true">school</i>
@@ -110,6 +162,7 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
<i class="material-icons mdc-button__icon" aria-hidden="true">attach_money</i> <i class="material-icons mdc-button__icon" aria-hidden="true">attach_money</i>
<span class="mdc-button__label">Donate</span> <span class="mdc-button__label">Donate</span>
</a> </a>
<div data-title="ACTIONS" id="divider"></div>
<div class="switch-container"> <div class="switch-container">
<div class="switch-wrapper"> <div class="switch-wrapper">
@@ -130,7 +183,15 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
<span>Currently showing Watch Party button</span> <span>Currently showing Watch Party button</span>
</div> </div>
</div> </div>
<div style="width: 100%; display: block; color: var(--mdc-theme-text-hint-on-dark)"> <div
style="
width: 100%;
display: block;
color: var(--mdc-theme-text-hint-on-dark);
font-size: 12.5px;
text-align: center;
"
>
Refresh page after changing show/hide status. Refresh page after changing show/hide status.
</div> </div>
</div> </div>
+16 -1
View File
@@ -23,6 +23,7 @@ import {
PLAYER_SOURCE, PLAYER_SOURCE,
getShowWPButton, getShowWPButton,
getTutorialStatus, getTutorialStatus,
setTutorialStatus,
} from './Api'; } from './Api';
import Tutorial from './Tutorial'; import Tutorial from './Tutorial';
@@ -74,6 +75,8 @@ const startResize = (ev) => {
const App = () => { const App = () => {
const closedNotification = { open: false, message: '' }; const closedNotification = { open: false, message: '' };
const [tutorialComponent, setTutorialComponent] = useState(null);
const [showFab, setShowFab] = useState(false);
const [tutorialComplete, setTutorialComplete] = useState(false); const [tutorialComplete, setTutorialComplete] = useState(false);
const [status, setStatus] = useState({ active: false, message: '' }); const [status, setStatus] = useState({ active: false, message: '' });
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
@@ -94,6 +97,7 @@ const App = () => {
setLoading(false); setLoading(false);
}); });
getShowWPButton().then((showWPButton) => { getShowWPButton().then((showWPButton) => {
setShowFab(showWPButton);
if (showWPButton === true) { if (showWPButton === true) {
document.querySelector('.watch-party-fab').classList.remove('watch-party-fab-hidden'); document.querySelector('.watch-party-fab').classList.remove('watch-party-fab-hidden');
} }
@@ -134,6 +138,11 @@ const App = () => {
if (document.fullscreenElement) setVisible(false); if (document.fullscreenElement) setVisible(false);
}; };
const resetTutorial = (c = null) => {
setTutorialComponent(c);
setTutorialComplete(false);
};
return ( return (
<ThemeProvider theme={darkTheme}> <ThemeProvider theme={darkTheme}>
<Snackbar <Snackbar
@@ -145,8 +154,11 @@ const App = () => {
autoHideDuration={6000} autoHideDuration={6000}
/> />
<Tutorial <Tutorial
setTutorialCompleteState={setTutorialComplete} resetTutorial={resetTutorial}
tutorialComplete={tutorialComplete} tutorialComplete={tutorialComplete}
showFab={showFab}
visible={visible}
tutorialComponent={tutorialComponent}
/> />
<div className="party-content-wrapper"> <div className="party-content-wrapper">
<div id="party-routes-wrapper"> <div id="party-routes-wrapper">
@@ -162,6 +174,9 @@ const App = () => {
{loading && <Loading />} {loading && <Loading />}
{status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? ( {status[APP_VERSION_STRING] && status[APP_VERSION_STRING].active === true ? (
<Routes <Routes
showFab={showFab}
resetTutorial={resetTutorial}
tutorialComplete={tutorialComplete}
updateLoading={setLoading} updateLoading={setLoading}
notify={(message) => setNotification({ open: true, message })} notify={(message) => setNotification({ open: true, message })}
appVersion={APP_VERSION} 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.'); this.props.notify('Uh oh. Got lost from the party.');
goTo(Create, this.props); goTo(Create, this.props);
return; return;
} else {
// CONTINUE TUTORIAL
if (this.props.tutorialComplete === false) {
this.props.resetTutorial('chat');
}
} }
if (response.messages) { if (response.messages) {
+34 -4
View File
@@ -37,6 +37,7 @@ import {
updateLocalData, updateLocalData,
getUserUid, getUserUid,
emptyLocalData, emptyLocalData,
setTutorialStatus,
} from './Api'; } from './Api';
import { goTo } from 'route-lite'; import { goTo } from 'route-lite';
import Chat from './Chat'; import Chat from './Chat';
@@ -90,7 +91,18 @@ export default class Create extends Component {
} }
componentDidMount() { componentDidMount() {
const { lastActive, userName, partyName, partyPin, allowAutoRejoin } = LocalData(); 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) { if (Math.abs(new Date(parseInt(lastActive)) - new Date().getTime()) <= 60000) {
this.props.updateLoading(true); this.props.updateLoading(true);
this.props.setVisible(true); this.props.setVisible(true);
@@ -262,7 +274,7 @@ export default class Create extends Component {
alertStep, alertStep,
expanded, expanded,
} = this.state; } = this.state;
const { status } = this.props; const { status, resetTutorial } = this.props;
return ( return (
<div className="party-create-container"> <div className="party-create-container">
<Typography <Typography
@@ -373,7 +385,10 @@ export default class Create extends Component {
<span>{mode === 'create' ? 'Start Party' : 'Join Party'}</span> <ChevronRight /> <span>{mode === 'create' ? 'Start Party' : 'Join Party'}</span> <ChevronRight />
</Button> </Button>
</Paper> </Paper>
<ExpansionPanel expanded={expanded === 'alerts'} className="create-settings-card"> <ExpansionPanel
expanded={expanded === 'alerts'}
className="create-settings-card create-alerts-card"
>
<ExpansionPanelSummary <ExpansionPanelSummary
onClick={() => this.handleExpanders('alerts')} onClick={() => this.handleExpanders('alerts')}
expandIcon={<ExpandLess />} expandIcon={<ExpandLess />}
@@ -431,7 +446,10 @@ export default class Create extends Component {
)} )}
</ExpansionPanelDetails> </ExpansionPanelDetails>
</ExpansionPanel> </ExpansionPanel>
<ExpansionPanel expanded={expanded === 'settings'} className="create-settings-card"> <ExpansionPanel
expanded={expanded === 'settings'}
className="create-settings-card create-settings-expander"
>
<ExpansionPanelSummary <ExpansionPanelSummary
onClick={() => this.handleExpanders('settings')} onClick={() => this.handleExpanders('settings')}
expandIcon={<ExpandLess />} expandIcon={<ExpandLess />}
@@ -482,6 +500,18 @@ export default class Create extends Component {
} }
labelPlacement="end" labelPlacement="end"
/> />
<Button
color="secondary"
fullWidth
variant="contained"
onClick={() => {
setTutorialStatus(false);
resetTutorial();
}}
size="small"
>
START TUTORIAL
</Button>
<Button <Button
color="secondary" color="secondary"
fullWidth fullWidth
+250 -5
View File
@@ -1,22 +1,267 @@
import React, { Component } from 'react'; 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 { export default class Tutorial extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { 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() { render() {
const { open } = this.state; const { open, index, el } = this.state;
setTimeout(() => {
this.setState({
el: this.getAnchorEl(),
});
}, 1000);
return ( return (
<Popover <Popover
hideBackdrop
className="watch-party-tutorial" className="watch-party-tutorial"
anchorEl={document.querySelector('.watch-party-fab')} anchorEl={el}
open={open} 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> </Popover>
); );
} }
+32
View File
@@ -25,6 +25,7 @@ body {
margin: 0 !important; margin: 0 !important;
background-color: black; background-color: black;
transition: max-width ease-in-out 0.35s; transition: max-width ease-in-out 0.35s;
overflow-y: initial !important;
} }
body.local { body.local {
background-color: white; background-color: white;
@@ -910,7 +911,38 @@ button.giphy-list-item {
.watch-party-tutorial { .watch-party-tutorial {
z-index: 9999 !important; z-index: 9999 !important;
height: 0;
} }
.watch-party-tutorial .MuiPaper-root.MuiPopover-paper { .watch-party-tutorial .MuiPaper-root.MuiPopover-paper {
padding: 20px; 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;
} }