v1.6.3/release
- virtual chat scroll - website update - version bump
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ import 'firebase/firestore';
|
||||
import Inactive from './Inactive';
|
||||
import { getUserUid, getPlayerSource, PLAYER_SOURCE } from './Api';
|
||||
|
||||
const APP_VERSION = '1.6.2';
|
||||
const APP_VERSION = '1.6.3';
|
||||
const APP_VERSION_STRING = APP_VERSION.replace(/\./g, '');
|
||||
|
||||
const darkTheme = createMuiTheme({
|
||||
|
||||
+25
-23
@@ -742,9 +742,13 @@ export default class Chat extends Component {
|
||||
</CardContent>
|
||||
) : (
|
||||
<CardContent>
|
||||
<Typography className="media-info-at" variant="caption">
|
||||
Nothing playing right now, pause or play once after starting a show to start
|
||||
sync.
|
||||
<Typography className="media-info-at" variant="button">
|
||||
Nothing playing right now
|
||||
<br />
|
||||
Pause or play once after starting a show to start sync.
|
||||
<br />
|
||||
Watch Party will not automatically change the show for you as this is a security
|
||||
exploit.
|
||||
</Typography>
|
||||
</CardContent>
|
||||
)}
|
||||
@@ -756,27 +760,25 @@ export default class Chat extends Component {
|
||||
</Card>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="thread-wrapper">
|
||||
<div className="alerts-container">
|
||||
{alerts.map((a) => {
|
||||
if (a.condition() === true) {
|
||||
return (
|
||||
<Card className="alert-card" variant="outlined">
|
||||
<CardContent className="alert-card-content">
|
||||
<Error />
|
||||
<Typography variant="body2">{a.message}</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
} else return null;
|
||||
})}
|
||||
</div>
|
||||
<Thread
|
||||
setReplyTo={this.setReplyTo}
|
||||
sendingMessages={sendingMessages}
|
||||
sentMessages={messages}
|
||||
/>
|
||||
<div className="alerts-container">
|
||||
{alerts.map((a) => {
|
||||
if (a.condition() === true) {
|
||||
return (
|
||||
<Card className="alert-card" variant="outlined">
|
||||
<CardContent className="alert-card-content">
|
||||
<Error />
|
||||
<Typography variant="body2">{a.message}</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
} else return null;
|
||||
})}
|
||||
</div>
|
||||
<Thread
|
||||
setReplyTo={this.setReplyTo}
|
||||
sendingMessages={sendingMessages}
|
||||
sentMessages={messages}
|
||||
/>
|
||||
<Paper
|
||||
square
|
||||
variant="outlined"
|
||||
|
||||
+16
-8
@@ -9,18 +9,24 @@ ALL CONTENT ON WATCH PARTY'S WEBSITE OR IN WATCH PARTY'S CHROME EXTENSION APP, U
|
||||
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
||||
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||
************************************************************************/
|
||||
.thread-container * {
|
||||
.thread-wrapper * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
letter-spacing: 1.15px;
|
||||
word-break: break-word !important;
|
||||
}
|
||||
.thread-container {
|
||||
max-height: none;
|
||||
padding: 0 15px;
|
||||
padding-right: 0px !important;
|
||||
overflow: hidden;
|
||||
.thread-wrapper {
|
||||
max-height: 100%;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
outline: none;
|
||||
}
|
||||
.thread-wrapper > div {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
.thread-item {
|
||||
color: white;
|
||||
@@ -56,11 +62,15 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
.thread-message .thread-overline span {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.thread-message .thread-overline > span {
|
||||
display: none;
|
||||
}
|
||||
.thread-message .thread-overline .thread-reply-icon {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -81,8 +91,6 @@ COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
.thread-item:hover .thread-message .thread-overline {
|
||||
height: 24px;
|
||||
margin-bottom: 7px;
|
||||
opacity: 1;
|
||||
}
|
||||
.thread-message p {
|
||||
|
||||
+103
-75
@@ -9,7 +9,7 @@ ALL CONTENT ON WATCH PARTY'S WEBSITE OR IN WATCH PARTY'S CHROME EXTENSION APP, U
|
||||
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
||||
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||
************************************************************************/
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, createRef } from 'react';
|
||||
import {
|
||||
Typography,
|
||||
IconButton,
|
||||
@@ -21,23 +21,32 @@ import {
|
||||
import { Reply, Send } from '@material-ui/icons';
|
||||
import './Thread.css';
|
||||
import { LocalData, webhookFetcher } from './Api';
|
||||
import { CellMeasurer, CellMeasurerCache, AutoSizer, List } from 'react-virtualized';
|
||||
|
||||
var cache = new CellMeasurerCache({
|
||||
fixedWidth: true,
|
||||
});
|
||||
|
||||
export default class Thread extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
autoSizeWidth: 0,
|
||||
};
|
||||
this.listRef = createRef();
|
||||
this.getMessage = this.getMessage.bind(this);
|
||||
this.getTimeString = this.getTimeString.bind(this);
|
||||
this.getReplyMessage = this.getReplyMessage.bind(this);
|
||||
this.getMessageTextOrImage = this.getMessageTextOrImage.bind(this);
|
||||
}
|
||||
scrollToMessage(id) {
|
||||
const pcc = document.querySelector('.thread-wrapper');
|
||||
const msg = document.getElementById(id);
|
||||
const alc = document.querySelector(
|
||||
'#party-routes-wrapper > div.party-chat-container > div.thread-wrapper > div.alerts-container'
|
||||
);
|
||||
pcc.scrollTop = msg.offsetTop - pcc.offsetTop - alc.clientHeight - 10;
|
||||
msg.classList.add('highlight');
|
||||
setTimeout(() => msg.classList.remove('highlight'), 2000);
|
||||
scrollToMessage(msgIdx, messages) {
|
||||
this.listRef.current.scrollToRow(msgIdx);
|
||||
setTimeout(() => {
|
||||
const id = messages[msgIdx].id || `sending-${msgIdx}`;
|
||||
const msg = document.getElementById(id);
|
||||
msg.classList.add('highlight');
|
||||
setTimeout(() => msg.classList.remove('highlight'), 2000);
|
||||
}, 500);
|
||||
}
|
||||
handleInteractiveMessageCall(msg) {
|
||||
const thanksElement = document.createElement('div');
|
||||
@@ -64,17 +73,17 @@ export default class Thread extends Component {
|
||||
}
|
||||
getItemClassNames(uid, userUid, msgIdx, messages, isSending = false) {
|
||||
const lastUid = msgIdx >= 1 ? messages[msgIdx - 1].uid : '';
|
||||
return `thread-item ${uid === userUid ? 'my-message' : ''} ${
|
||||
isSending ? 'sending-message' : ''
|
||||
} ${uid === '<system>' ? 'system-message' : ''} ${lastUid === uid ? 'continued-message' : ''}`;
|
||||
return `thread-item ${uid === userUid ? 'my-message ' : ''}${
|
||||
isSending ? 'sending-message ' : ''
|
||||
}${uid === '<system>' ? 'system-message ' : ''}${lastUid === uid ? 'continued-message' : ''}`;
|
||||
}
|
||||
getMessageTextOrImage(msg) {
|
||||
getMessageTextOrImage(msg, measure) {
|
||||
if (msg.type === 'giphy') {
|
||||
return <img alt="gif" src={msg.text} />;
|
||||
return <img onLoad={measure} alt="gif" src={msg.text} />;
|
||||
}
|
||||
if (msg.type === 'interactive/text') {
|
||||
return (
|
||||
<Paper elevation={0} className="thread-interactive-text">
|
||||
<Paper onLoad={measure} elevation={0} className="thread-interactive-text">
|
||||
<Typography className="thread-interactive-question" variant="overline">
|
||||
{msg.text}
|
||||
</Typography>
|
||||
@@ -101,7 +110,7 @@ export default class Thread extends Component {
|
||||
}
|
||||
if (msg.type === 'interactive/link') {
|
||||
return (
|
||||
<Paper elevation={0} className="thread-interactive-text">
|
||||
<Paper onLoad={measure} elevation={0} className="thread-interactive-text">
|
||||
<Typography className="thread-interactive-question" variant="overline">
|
||||
{msg.text}
|
||||
</Typography>
|
||||
@@ -117,75 +126,94 @@ export default class Thread extends Component {
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
return <p>{msg.text}</p>;
|
||||
return <p onLoad={measure}>{msg.text}</p>;
|
||||
}
|
||||
getTimeString(time) {
|
||||
return new Date(time.seconds * 1000).toLocaleTimeString();
|
||||
}
|
||||
getReplyMessage(rT, messages) {
|
||||
if (rT !== undefined && rT !== null) {
|
||||
const replyMessage = messages.filter((m) => m.id === rT)[0];
|
||||
return (
|
||||
<div className="thread-reply" onClick={() => this.scrollToMessage(replyMessage.id)}>
|
||||
<p className="thread-reply-name">Reply to {replyMessage.name}:</p>
|
||||
{this.getMessageTextOrImage(replyMessage)}
|
||||
</div>
|
||||
);
|
||||
getReplyMessage(replyTo, messages) {
|
||||
if (replyTo !== undefined && replyTo !== null) {
|
||||
const replyMessage = messages.filter((v) => v.id === replyTo)[0];
|
||||
if (replyMessage) {
|
||||
const msgIdx = messages.indexOf(replyMessage);
|
||||
return (
|
||||
<div className="thread-reply" onClick={() => this.scrollToMessage(msgIdx, messages)}>
|
||||
<p className="thread-reply-name">Reply to {replyMessage.name}:</p>
|
||||
{this.getMessageTextOrImage(replyMessage)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
render() {
|
||||
const { sendingMessages, setReplyTo, sentMessages } = this.props;
|
||||
getMessage(params) {
|
||||
const { autoSizeWidth } = this.state;
|
||||
const { sendingMessages, sentMessages, setReplyTo } = this.props;
|
||||
const { userUid } = LocalData();
|
||||
const messages = [...sentMessages, ...sendingMessages];
|
||||
const msg = messages[params.index];
|
||||
const msgIdx = params.index;
|
||||
return (
|
||||
<div className="thread-container">
|
||||
{sentMessages.length > 0
|
||||
? sentMessages.map((msg, msgIdx) => (
|
||||
<div
|
||||
id={msg.id}
|
||||
key={`msg-${msgIdx}`}
|
||||
className={this.getItemClassNames(msg.uid, userUid, msgIdx, sentMessages)}
|
||||
>
|
||||
<div className="thread-name">{msg.name}</div>
|
||||
{this.getReplyMessage(msg.replyTo, sentMessages)}
|
||||
<div className="thread-message">
|
||||
<div className="thread-overline">
|
||||
<span>{this.getTimeString(msg.time)}</span>
|
||||
<div className="thread-reply-icon">
|
||||
<IconButton onClick={() => setReplyTo(msg)}>
|
||||
<Reply />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
{this.getMessageTextOrImage(msg)}
|
||||
<CellMeasurer
|
||||
cache={cache}
|
||||
columnIndex={0}
|
||||
key={`msg-${msgIdx}`}
|
||||
parent={params.parent}
|
||||
rowIndex={msgIdx}
|
||||
width={autoSizeWidth}
|
||||
>
|
||||
{({ measure, registerChild }) => (
|
||||
<div
|
||||
ref={registerChild}
|
||||
style={params.style}
|
||||
id={msg.id || `sending-${msgIdx}`}
|
||||
key={`msg-${msgIdx}-item`}
|
||||
className={this.getItemClassNames(msg.uid, userUid, msgIdx, messages, !!!msg.id)}
|
||||
>
|
||||
<div className="thread-name">{msg.name}</div>
|
||||
{this.getReplyMessage(msg.replyTo, messages)}
|
||||
<div className="thread-message">
|
||||
<div className="thread-overline">
|
||||
<span>{this.getTimeString(msg.time)}</span>
|
||||
<div className="thread-reply-icon">
|
||||
<IconButton onClick={() => setReplyTo(msg)}>
|
||||
<Reply />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
: null}
|
||||
{sendingMessages.length > 0
|
||||
? sendingMessages.map((msg, msgIdx) => (
|
||||
<div
|
||||
id={msg.id}
|
||||
key={`msg-${msgIdx}`}
|
||||
className={this.getItemClassNames(msg.uid, userUid, msgIdx, sendingMessages, true)}
|
||||
>
|
||||
<div className="thread-name">{msg.name}</div>
|
||||
{this.getReplyMessage(msg.replyTo, sentMessages)}
|
||||
<div className="thread-message">
|
||||
<div className="thread-overline">
|
||||
<span>{this.getTimeString(msg.time)}</span>
|
||||
<div className="thread-reply-icon">
|
||||
<IconButton onClick={() => setReplyTo(msg)}>
|
||||
<Reply />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
{this.getMessageTextOrImage(msg)}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
{this.getMessageTextOrImage(msg, measure)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CellMeasurer>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { autoSizeWidth } = this.state;
|
||||
const { sendingMessages, sentMessages } = this.props;
|
||||
return (
|
||||
<AutoSizer style={{ flex: 1 }}>
|
||||
{({ height, width }) => {
|
||||
if (autoSizeWidth && autoSizeWidth !== width) {
|
||||
cache.clearAll();
|
||||
this.listRef.current.recomputeRowHeights();
|
||||
this.setState({ autoSizeWidth: width });
|
||||
}
|
||||
|
||||
return (
|
||||
<List
|
||||
className="thread-wrapper"
|
||||
deferredMeasurementCache={cache}
|
||||
height={height}
|
||||
width={width}
|
||||
ref={this.listRef}
|
||||
rowCount={sendingMessages.length + sentMessages.length}
|
||||
rowHeight={({ index }) => cache.rowHeight({ index }) + 10}
|
||||
rowRenderer={this.getMessage}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</AutoSizer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,14 +378,6 @@ body.disney #party_wrapper * {
|
||||
.create-bottom-card a:hover {
|
||||
color: #c0f300;
|
||||
}
|
||||
.thread-wrapper {
|
||||
max-height: 100%;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.room-title {
|
||||
text-overflow: ellipsis !important;
|
||||
word-break: break-word !important;
|
||||
@@ -585,7 +577,6 @@ body.amazon-prime .notification-switch .MuiSwitch-thumb {
|
||||
|
||||
.alerts-container {
|
||||
margin: 5px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 5px 0;
|
||||
z-index: 999 !important;
|
||||
|
||||
Reference in New Issue
Block a user