Skip to content

Commit

Permalink
Video chat bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tiller1010 committed Jul 10, 2022
1 parent 8104475 commit f02563f
Show file tree
Hide file tree
Showing 11 changed files with 255 additions and 81 deletions.
27 changes: 21 additions & 6 deletions js/components/AccountProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,29 @@ class AccountProfile extends React.Component {
<PremiumVideoChatListingForm user={authenticatedUser}/>
<p>
{authenticatedUser.connectedStripeAccountID ?
<p className="desktop-hide">Stripe Account ID: {authenticatedUser.connectedStripeAccountID}</p>
<>
{this.props.stripeAccountPending ?
<>
<p><b>!! Your Connected Stripe Account still needs to be completed, or is pending verification. !!</b></p>
<p>Your video chat listing will not be purchasable until your connected Stripe account is completed and verified.</p>
<a href={`/manage-stripe-account/${authenticatedUser.connectedStripeAccountID}`} className="button">
Complete Stripe Account
<FontAwesomeIcon icon={faUser}/>
</a>
</>
:
<a href={`/manage-stripe-account/${authenticatedUser.connectedStripeAccountID}`} className="button">
Manage Stripe Account
<FontAwesomeIcon icon={faUser}/>
</a>
}
</>
:
''
<a href={`/manage-stripe-account/`} className="button">
Create Connected Stripe Account
<FontAwesomeIcon icon={faUser}/>
</a>
}
<a href={`/manage-stripe-account/${authenticatedUser.connectedStripeAccountID || ''}`} className="button">
Manage Stripe Account
<FontAwesomeIcon icon={faUser}/>
</a>
</p>
</>
:
Expand Down
21 changes: 13 additions & 8 deletions js/components/PremiumVideoChatListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,28 @@ export default class PremiumVideoChatListing extends React.Component<PremiumVide
switch(this.props.view){
case 'owner':
return timeSlots.map((timeSlot) =>
<div key={timeSlots.indexOf(timeSlot)}>
<div key={timeSlots.indexOf(timeSlot)} style={{ margin: '10px 0', borderBottom: '1px dotted black' }}>
{timeSlot.customerUserID ?
<div>
<p><b>Video Chat with: {timeSlot.customerDisplayName}</b></p>
<p><b>{timeSlot.date} - {timeSlot.time.convertTo12HourTime()}</b></p>
<a className="button" href={`/video-chat?forUserID=${timeSlot.customerUserID}`}>
Go to Video Chat
<FontAwesomeIcon icon={faLongArrowAltRight}/>
</a>
<div className="field checkbox" style={{ whiteSpace: 'nowrap' }}>
{/* @ts-ignore */}
<input id={`timeSlot${timeSlots.indexOf(timeSlot)}`} type="checkbox" checked={timeSlot.completed} onClick={(e) => this.handleTimeSlotChange(e.target.checked, timeSlots.indexOf(timeSlot))}/>
{/* @ts-ignore */}
<label htmlFor={`timeSlot${timeSlots.indexOf(timeSlot)}`}>{timeSlot.date} - {timeSlot.time.convertTo12HourTime()} with User: {timeSlot.customerDisplayName}</label>
<label htmlFor={`timeSlot${timeSlots.indexOf(timeSlot)}`}>Mark Completed</label>
</div>
<a className="button" href={`/video-chat?forUserID=${timeSlot.customerUserID}`}>
Go to Video Chat
<FontAwesomeIcon icon={faLongArrowAltRight}/>
</a>
</div>
:
<>
{/* @ts-ignore */}
<div>{timeSlot.date} - {timeSlot.time.convertTo12HourTime()} Available</div>
<div style={{ margin: '10px 0', minHeight: '36px', display: 'inline-flex', alignItems: 'center' }}>
<b>Available</b><span>&nbsp;{timeSlot.date} - {timeSlot.time.convertTo12HourTime()}</span>
</div>
</>
}
</div>
Expand Down Expand Up @@ -317,7 +321,8 @@ export default class PremiumVideoChatListing extends React.Component<PremiumVide
{this.renderTimeSlots()}
</div>

{this.props.view == 'customer' ?
{/* Only Show Buy button if customer selected timeslots */}
{this.props.view == 'customer' && this.state.timeSlots.filter(timeSlot => timeSlot.tempCustomerUserID).length ?
<button className="button" onClick={() => this.handleBuyNow()}>
Buy Now
<FontAwesomeIcon icon={faPlus}/>
Expand Down
33 changes: 31 additions & 2 deletions js/components/PremiumVideoChatListingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import graphQLFetch from '../graphQLFetch.js';
import PremiumVideoChatListing from './PremiumVideoChatListing.tsx';
// @ts-ignore
import RemoveConfirmationModal from './RemoveConfirmationModal.tsx';
import { initFramewerk } from 'werkbot-framewerk';

function findInputElement(element) {
if (!element) return;
let answerElement = element.querySelector('input');
if (!answerElement) {
return findInputElement(element.parentElement)
} else {
return answerElement;
}
}

interface User {
_id: string;
Expand Down Expand Up @@ -72,6 +83,7 @@ export default class PremiumVideoChatListingForm extends React.Component<Premium
savedAllChanges: true,
}
this.state = state;
this.handlePriceChange = this.handlePriceChange.bind(this);
this.handleThumbnailChange = this.handleThumbnailChange.bind(this);
this.handleTimeSlotChange = this.handleTimeSlotChange.bind(this);
this.handleRemoveTimeSlot = this.handleRemoveTimeSlot.bind(this);
Expand All @@ -85,8 +97,26 @@ export default class PremiumVideoChatListingForm extends React.Component<Premium
this.setState({ ...this.props.user.premiumVideoChatListing });
this.setState({ savedPremiumVideoChatListing: this.props.user.premiumVideoChatListing });
}

// Make sure generated buttons effect state
const numericButtonsCheck = setInterval(() => {
const generatedButtons = document.querySelectorAll('.field.numeric > span')
if (generatedButtons.length === 2) {
clearInterval(numericButtonsCheck)
generatedButtons.forEach((controlIcon) => {
controlIcon.addEventListener('click', (e) => {
// @ts-ignore
const input = findInputElement(e.target.parentElement);
this.handlePriceChange({ target: { value: input.value } });
});
});
}
}, 100);
}

handlePriceChange(event) {
this.setState({price: Number(event.target.value), savedAllChanges: false});
}

handleThumbnailChange(event){
const context = this;
Expand Down Expand Up @@ -145,7 +175,6 @@ export default class PremiumVideoChatListingForm extends React.Component<Premium
time: '',
booked: false,
completed: false,
savedAllChanges: false,
}
]
});
Expand Down Expand Up @@ -340,7 +369,7 @@ export default class PremiumVideoChatListingForm extends React.Component<Premium
</div>
<div className="field numeric">
<label htmlFor="priceField">Price</label>
<input type="number" min="0.50" step="0.01" name="price" id="priceField" value={price} onChange={(event) => this.setState({price: Number(event.target.value), savedAllChanges: false})}/>
<input type="number" min="0.50" step="0.01" name="price" id="priceField" value={price} onChange={this.handlePriceChange}/>
<p><i>Application fees will be applied</i></p>
</div>
<div className="field text">
Expand Down
6 changes: 4 additions & 2 deletions js/components/Product.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ export default class Product extends React.Component<ProductProps, ProductState>
{timeSlots.length ?
timeSlots.map((timeSlot) =>
<div key={timeSlots.indexOf(timeSlot)}>
<a className="button" href={`/video-chat?withUserID=${productObject.userID}`}>
Video Chat with User: {this.state.ownerDisplayName} on {timeSlot.date} - {timeSlot.time.convertTo12HourTime()}
<p><b>Video Chat with: {this.state.ownerDisplayName}</b></p>
<p><b>{timeSlot.date} - {timeSlot.time.convertTo12HourTime()}</b></p>
<a className="button" href={`/video-chat?withUserID=${productObject.userID}`} aria-label={`Go to Video Chat with ${this.state.ownerDisplayName}`}>
Go to Video Chat
<FontAwesomeIcon icon={faLongArrowAltRight}/>
</a>
</div>
Expand Down
38 changes: 24 additions & 14 deletions js/components/VideoChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,19 @@ export default class VideoChat extends React.Component<VideoChatProps, VideoChat
});
}

hangup(){
const { peerConnection, availableCalls } = this.state;
async hangup(){
// const { peerConnection } = this.state;

peerConnection.close();
// peerConnection.close();

this.webcamVideo.current.srcObject = null;
this.remoteVideo.current.srcObject = null;

const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
localStream.getTracks().forEach((track) => {
track.stop();
});

this.setState({
callID: '',
webcamButtonDisabled: false,
Expand Down Expand Up @@ -361,6 +366,7 @@ export default class VideoChat extends React.Component<VideoChatProps, VideoChat
<div className="pure-u-1 pure-u-md-1-2">
<div className="pad">
<h2>Join a Call</h2>
<p>Select the most recent call offer</p>
<p>Not seeing the right call? Try clicking refresh.</p>
<button className="button" id="refreshButton" onClick={this.refreshCallOffers}>
Refresh
Expand All @@ -370,10 +376,11 @@ export default class VideoChat extends React.Component<VideoChatProps, VideoChat
<div className="flex y-center field optionset">
{availableCalls ?
availableCalls.map((callOffer) =>
<div key={availableCalls.indexOf(callOffer)}>
<div key={availableCalls.indexOf(callOffer)} style={{ maxWidth: '100%' }}>
<p><b>{callOffer.withUserDisplayName}</b></p>
<div style={{ whiteSpace: 'nowrap' }}>
<input type="radio" id={`callOffer_${callOffer.callID}`} name="callID" onClick={() => this.setState({ callID: callOffer.callID})}/>
<label htmlFor={`callOffer_${callOffer.callID}`}>With {callOffer.withUserDisplayName}, created call on {callOffer.createdDate}</label>
<label htmlFor={`callOffer_${callOffer.callID}`} style={{ maxWidth: '100%', whiteSpace: 'normal' }}>&nbsp;Call created on {callOffer.createdDate}</label>
</div>
<button className="button" id="answerButton" disabled={answerButtonDisabled || callID != callOffer.callID} onClick={this.answerCall}>
Answer
Expand Down Expand Up @@ -417,15 +424,18 @@ export default class VideoChat extends React.Component<VideoChatProps, VideoChat
</div>
</div>
</div>
<div className="flex x-center pure-u-1">
<button className="button" id="webcamButton" disabled={this.state.webcamButtonDisabled} onClick={this.startWebcam}>
Start webcam
<FontAwesomeIcon icon={faCamera}/>
</button>
</div>
<div className="flex x-center y-center">
{this.renderCallControls()}
</div>
{this.state.webcamButtonDisabled ?
<div className="flex x-center y-center">
{this.renderCallControls()}
</div>
:
<div className="flex x-center pure-u-1">
<button className="button" id="webcamButton" onClick={this.startWebcam}>
Start webcam
<FontAwesomeIcon icon={faCamera}/>
</button>
</div>
}
<div className="flex x-center pure-u-1">
<button className="button" id="hangupButton" disabled={this.state.hangupButtonDisabled} onClick={this.hangup}>
Hangup
Expand Down
3 changes: 2 additions & 1 deletion js/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ if(document.getElementById('account-profile')){
var userID = document.getElementById('account-profile').getAttribute('userid');
var authenticatedUserID = document.getElementById('account-profile').getAttribute('authenticateduserid');
var isCurrentUser = document.getElementById('account-profile').getAttribute('iscurrentuser');
var stripeAccountPending = document.getElementById('account-profile').getAttribute('stripeaccountpending');
var pathResolver = document.getElementById('account-profile').getAttribute('pathresolver');
ReactDOM.render(<AccountProfile userID={userID} authenticatedUserID={authenticatedUserID} isCurrentUser={eval(isCurrentUser)} pathResolver={pathResolver}/>, document.getElementById('account-profile'));
ReactDOM.render(<AccountProfile userID={userID} authenticatedUserID={authenticatedUserID} isCurrentUser={eval(isCurrentUser)} stripeAccountPending={eval(stripeAccountPending)} pathResolver={pathResolver}/>, document.getElementById('account-profile'));
}
if(document.getElementById('video-chat')){
var authenticatedUserID = document.getElementById('video-chat').getAttribute('authenticateduserid');
Expand Down
Loading

0 comments on commit f02563f

Please sign in to comment.