Finish room camera

This commit is contained in:
Bill 2021-08-08 22:21:40 -04:00
parent 16773c0501
commit a34235f16d
6 changed files with 75 additions and 51 deletions

View File

@ -167,7 +167,7 @@
}
.nitro-camera-checkout {
width: 336px;
width: 388px;
.picture-preview {
width: 320px;

View File

@ -1,4 +1,4 @@
import { InitCameraMessageEvent, IRoomCameraWidgetEffect, IRoomCameraWidgetSelectedEffect, RequestCameraConfigurationComposer, RoomCameraWidgetManagerEvent } from '@nitrots/nitro-renderer';
import { InitCameraMessageEvent, IRoomCameraWidgetEffect, RequestCameraConfigurationComposer, RoomCameraWidgetManagerEvent } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetRoomCameraWidgetManager } from '../../../../api';
import { RoomWidgetCameraEvent } from '../../../../events/room-widgets/camera/RoomWidgetCameraEvent';
@ -22,10 +22,8 @@ export const CameraWidgetView: FC<{}> = props =>
const [ availableEffects, setAvailableEffects ] = useState<IRoomCameraWidgetEffect[]>([]);
const [ cameraRoll, setCameraRoll ] = useState<CameraPicture[]>([]);
const [ selectedPictureIndex, setSelectedPictureIndex ] = useState(-1);
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
const [ isZoomed, setIsZoomed ] = useState(false);
const [ myLevel, setMyLevel ] = useState(1);
const [ savedPictureUrl, setSavedPictureUrl ] = useState<string>(null);
const [ myLevel, setMyLevel ] = useState(10);
const [ base64Url, setSavedPictureUrl ] = useState<string>(null);
const [ price, setPrice ] = useState<{ credits: number, duckets: number, publishDucketPrice: number }>(null);
const onNitroEvent = useCallback((event: RoomWidgetCameraEvent) =>
@ -113,10 +111,10 @@ export const CameraWidgetView: FC<{}> = props =>
}, []);
return (
<CameraWidgetContextProvider value={ { cameraRoll, setCameraRoll, selectedPictureIndex, setSelectedPictureIndex, selectedEffects, setSelectedEffects, isZoomed, setIsZoomed } }>
<CameraWidgetContextProvider value={ { cameraRoll, setCameraRoll, selectedPictureIndex, setSelectedPictureIndex } }>
{ (mode === MODE_CAPTURE) && <CameraWidgetCaptureView onClose={ () => processAction('close') } onEdit={ () => processAction('edit') } onDelete={ () => processAction('delete') } /> }
{ (mode === MODE_EDITOR) && <CameraWidgetEditorView picture={ cameraRoll[selectedPictureIndex] } myLevel={ myLevel } onClose={ () => processAction('close') } onCancel={ () => processAction('editor_cancel') } onCheckout={ checkoutPictureUrl } availableEffects={ availableEffects } /> }
{ (mode === MODE_CHECKOUT) && <CameraWidgetCheckoutView pictureUrl={ savedPictureUrl } onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } price={ price }></CameraWidgetCheckoutView> }
{ (mode === MODE_CHECKOUT) && <CameraWidgetCheckoutView base64Url={ base64Url } onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } price={ price }></CameraWidgetCheckoutView> }
</CameraWidgetContextProvider>
);
}

View File

@ -5,11 +5,7 @@ const CameraWidgetContext = createContext<ICameraWidgetContext>({
cameraRoll: null,
setCameraRoll: null,
selectedPictureIndex: null,
setSelectedPictureIndex: null,
selectedEffects: null,
setSelectedEffects: null,
isZoomed: null,
setIsZoomed: null
setSelectedPictureIndex: null
});
export const CameraWidgetContextProvider: FC<CameraWidgetContextProps> = props =>

View File

@ -1,4 +1,3 @@
import { IRoomCameraWidgetSelectedEffect } from '@nitrots/nitro-renderer';
import { Dispatch, ProviderProps, SetStateAction } from 'react';
import { CameraPicture } from '../common/CameraPicture';
@ -8,10 +7,6 @@ export interface ICameraWidgetContext
setCameraRoll: Dispatch<SetStateAction<CameraPicture[]>>;
selectedPictureIndex: number,
setSelectedPictureIndex: Dispatch<SetStateAction<number>>;
selectedEffects: IRoomCameraWidgetSelectedEffect[],
setSelectedEffects: Dispatch<SetStateAction<IRoomCameraWidgetSelectedEffect[]>>;
isZoomed: boolean,
setIsZoomed: Dispatch<SetStateAction<boolean>>;
}
export interface CameraWidgetContextProps extends ProviderProps<ICameraWidgetContext>

View File

@ -1,36 +1,32 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import { CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, PublishPhotoMessageComposer, PurchasePhotoMessageComposer } from '@nitrots/nitro-renderer';
import { CameraPublishStatusMessageEvent, CameraPurchaseOKMessageEvent, CameraStorageUrlMessageEvent, PublishPhotoMessageComposer, PurchasePhotoMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react';
import { GetRoomEngine } from '../../../../../../api';
import { GetConfiguration, GetRoomEngine } from '../../../../../../api';
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks/messages/message-event';
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../../../layout';
import { LocalizeText } from '../../../../../../utils/LocalizeText';
import { CurrencyIcon } from '../../../../../shared/currency-icon/CurrencyIcon';
import { useCameraWidgetContext } from '../../context/CameraWidgetContext';
import { CameraWidgetCheckoutViewProps } from './CameraWidgetCheckoutView.types';
export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props =>
{
const { pictureUrl = null, onCloseClick = null, onCancelClick = null, price = null } = props;
const { base64Url = null, onCloseClick = null, onCancelClick = null, price = null } = props;
const [ pictureUrl, setPictureUrl ] = useState<string>(null);
const [ publishUrl, setPublishUrl ] = useState<string>(null);
const [ picturesBought, setPicturesBought ] = useState(0);
const [ wasPicturePublished, setWasPicturePublished ] = useState(false);
const [ isWaiting, setIsWaiting ] = useState(false);
const [ publishCooldown, setPublishCooldown ] = useState(0);
const { cameraRoll = null, selectedPictureIndex = -1, selectedEffects = null, isZoomed = false } = useCameraWidgetContext();
useEffect(() =>
{
if(!pictureUrl) return;
if(!base64Url) return;
console.log(pictureUrl);
GetRoomEngine().saveBase64AsScreenshot(pictureUrl);
}, [ pictureUrl ]);
GetRoomEngine().saveBase64AsScreenshot(base64Url);
}, [ base64Url ]);
const onCameraPurchaseOKMessageEvent = useCallback((event: CameraPurchaseOKMessageEvent) =>
{
console.log(event);
setPicturesBought(value => value + 1);
setPicturesBought(value => (value + 1));
setIsWaiting(false);
}, []);
@ -40,8 +36,7 @@ export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props
{
const parser = event.getParser();
console.log(parser);
setPublishUrl(parser.extraDataId);
setPublishCooldown(parser.secondsToWait);
setWasPicturePublished(parser.ok);
setIsWaiting(false);
@ -49,6 +44,15 @@ export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props
CreateMessageHook(CameraPublishStatusMessageEvent, onCameraPublishStatusMessageEvent);
const onCameraStorageUrlMessageEvent = useCallback((event: CameraStorageUrlMessageEvent) =>
{
const parser = event.getParser();
setPictureUrl(GetConfiguration<string>('camera.url') + '/' + parser.url);
}, []);
CreateMessageHook(CameraStorageUrlMessageEvent, onCameraStorageUrlMessageEvent);
const processAction = useCallback((type: string, value: string | number = null) =>
{
switch(type)
@ -60,7 +64,7 @@ export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props
if(isWaiting) return;
setIsWaiting(true);
SendMessageHook(new PurchasePhotoMessageComposer('1_1627697499'));
SendMessageHook(new PurchasePhotoMessageComposer(''));
return;
case 'publish':
if(isWaiting) return;
@ -80,27 +84,58 @@ export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props
<NitroCardView className="nitro-camera-checkout" simple={ true }>
<NitroCardHeaderView headerText={ LocalizeText('camera.confirm_phase.title') } onCloseClick={ event => processAction('close') } />
<NitroCardContentView>
<div className="picture-preview border mb-2" style={ { backgroundImage: 'url(' + null + ')' } }></div>
<div className="bg-muted rounded p-2 text-black mb-2 d-flex justify-content-between align-items-center">
<div>
<div className="fw-bold d-flex justify-content-start">{ LocalizeText('camera.purchase.header') }{ price.credits > 0 && <>: { price.credits } <CurrencyIcon type={ -1 } /></> }</div>
{ picturesBought > 0 && <div>{ LocalizeText('camera.purchase.count.info') + ' ' + picturesBought }</div> }
<div className="d-flex justify-content-center align-items-center picture-preview border mb-2" style={ pictureUrl ? { backgroundImage: 'url(' + pictureUrl + ')' } : {} }>
{ !pictureUrl &&
<div className="text-black fw-bold">
{ LocalizeText('camera.loading') }
</div> }
</div>
{ pictureUrl && <div className="text-black mb-2">{ LocalizeText('camera.confirm_phase.info') }</div> }
<div className="d-flex justify-content-between bg-muted rounded p-2 text-black mb-2">
<div className="d-flex flex-column">
<div className="fw-bold d-flex justify-content-start">{ LocalizeText('camera.purchase.header') }</div>
{ ((price.credits > 0) || (price.duckets > 0)) &&
<div className="d-flex">
<div className="me-1">{ LocalizeText('catalog.purchase.confirmation.dialog.cost') }</div>
{ (price.credits > 0) &&
<div className="d-flex fw-bold">
{ price.credits } <CurrencyIcon type={ -1 } />
</div> }
{ (price.duckets > 0) &&
<div className="d-flex fw-bold">
{ price.duckets } <CurrencyIcon type={ 5 } />
</div> }
</div> }
{ (picturesBought > 0) &&
<div>
<span className="fw-bold">{ LocalizeText('camera.purchase.count.info') }</span> { picturesBought }
<u className="ms-1">{ LocalizeText('camera.open.inventory') }</u>
</div> }
</div>
<div>
<button className="btn btn-success" disabled={ isWaiting } onClick={ event => processAction('buy') }>{ LocalizeText(picturesBought === 0 ? 'buy' : 'camera.buy.another.button.text') }</button>
{ picturesBought > 0 && <div className="mt-1 text-center"><a href="#">{ LocalizeText('camera.open.inventory') }</a></div> }
<div className="d-flex align-items-center">
<button className="btn btn-success" disabled={ isWaiting } onClick={ event => processAction('buy') }>{ LocalizeText(!picturesBought ? 'buy' : 'camera.buy.another.button.text') }</button>
</div>
</div>
<div className="bg-muted rounded p-2 text-black mb-2">
<div className="d-flex justify-content-between align-items-center">
<div className="me-2">
<div className="fw-bold d-flex justify-content-start">{ LocalizeText(wasPicturePublished ? 'camera.publish.successful' : 'camera.publish.explanation') }{ !wasPicturePublished && price.duckets > 0 && <>: { price.duckets } <CurrencyIcon type={ price.publishDucketPrice } /></> }</div>
<div>{ LocalizeText(wasPicturePublished ? 'camera.publish.success.short.info' : 'camera.publish.detailed.explanation') }</div>
{ wasPicturePublished && <a href="#">{ LocalizeText('camera.link.to.published') }</a> }
<div className="d-flex justify-content-between bg-muted rounded p-2 text-black mb-2">
<div className="d-flex flex-column">
<div className="fw-bold d-flex justify-content-start">{ LocalizeText(wasPicturePublished ? 'camera.publish.successful' : 'camera.publish.explanation') }</div>
<div>
{ LocalizeText(wasPicturePublished ? 'camera.publish.success.short.info' : 'camera.publish.detailed.explanation') }
</div>
{ !wasPicturePublished && <button className="btn btn-success" disabled={ isWaiting || publishCooldown > 0 } onClick={ event => processAction('publish') }>{ LocalizeText('camera.publish.button.text') }</button> }
{ wasPicturePublished && <a href={ publishUrl } rel="noreferrer" target="_blank">{ LocalizeText('camera.link.to.published') }</a> }
{ !wasPicturePublished && (price.publishDucketPrice > 0) &&
<div className="d-flex">
<div className="me-1">{ LocalizeText('catalog.purchase.confirmation.dialog.cost') }</div>
<div className="d-flex fw-bold">
{ price.publishDucketPrice } <CurrencyIcon type={ 5 } />
</div>
</div> }
{ (publishCooldown > 0) && <div className="mt-1 text-center fw-bold">{ LocalizeText('camera.publish.wait', [ 'minutes' ], [ Math.ceil( publishCooldown / 60).toString() ]) }</div> }
</div>
{ publishCooldown > 0 && <div className="mt-1 text-center fw-bold">{ LocalizeText('camera.publish.wait', ['minutes'], [Math.ceil(publishCooldown/60).toString()]) }</div> }
{ !wasPicturePublished &&
<div className="d-flex align-items-end">
<button className="btn btn-success" disabled={ isWaiting || publishCooldown > 0 } onClick={ event => processAction('publish') }>{ LocalizeText('camera.publish.button.text') }</button>
</div> }
</div>
<div className="text-black mb-2 text-center">{ LocalizeText('camera.warning.disclaimer') }</div>
<div className="d-flex justify-content-end">

View File

@ -1,6 +1,6 @@
export interface CameraWidgetCheckoutViewProps
{
pictureUrl: string;
base64Url: string;
onCloseClick: () => void;
onCancelClick: () => void;
price: { credits: number, duckets: number, publishDucketPrice: number };