mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-27 08:00:51 +01:00
RoomWidgetCamera updates
This commit is contained in:
parent
ff2cf1ac4c
commit
cd7acf6348
@ -5,7 +5,13 @@ $nitro-card-top-height: $nitro-card-header-height + $nitro-card-tabs-height;
|
|||||||
.nitro-card {
|
.nitro-card {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
.nitro-card-close-parent {
|
@import './content/NitroCardContentView';
|
||||||
|
@import './header/NitroCardHeaderView';
|
||||||
|
@import './simple-header/NitroCardSimpleHeaderView';
|
||||||
|
@import './tabs/NitroCardTabsView';
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-card-close-parent {
|
||||||
right: -3px;
|
right: -3px;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -28,12 +34,6 @@ $nitro-card-top-height: $nitro-card-header-height + $nitro-card-tabs-height;
|
|||||||
filter: brightness(0.8);
|
filter: brightness(0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@import './content/NitroCardContentView';
|
|
||||||
@import './header/NitroCardHeaderView';
|
|
||||||
@import './simple-header/NitroCardSimpleHeaderView';
|
|
||||||
@import './tabs/NitroCardTabsView';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nitro-card-responsive {
|
.nitro-card-responsive {
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
.nitro-camera-capture {
|
.nitro-camera-capture {
|
||||||
|
.nitro-card-close-parent {
|
||||||
|
top: 7px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.camera-canvas {
|
.camera-canvas {
|
||||||
width: 340px;
|
width: 340px;
|
||||||
height: 462px;
|
height: 462px;
|
||||||
@ -9,7 +14,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
height: 320px;
|
height: 320px;
|
||||||
margin-top: 9px;
|
margin-top: 37px;
|
||||||
margin-left: 11.4px;
|
margin-left: 11.4px;
|
||||||
|
|
||||||
&.bg {
|
&.bg {
|
||||||
@ -25,7 +30,7 @@
|
|||||||
width: 94px;
|
width: 94px;
|
||||||
height: 94px;
|
height: 94px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-top: 334px;
|
margin-top: 362px;
|
||||||
|
|
||||||
background-image: url('../../../../assets/images/room-widgets/camera-widget/camera-spritesheet.png');
|
background-image: url('../../../../assets/images/room-widgets/camera-widget/camera-spritesheet.png');
|
||||||
background-position: -340px 0px;
|
background-position: -340px 0px;
|
||||||
@ -94,10 +99,19 @@
|
|||||||
width: 320px;
|
width: 320px;
|
||||||
height: 320px;
|
height: 320px;
|
||||||
|
|
||||||
&.zoomed {
|
.slider {
|
||||||
background-size: 636px;
|
background: linear-gradient(180deg, transparent, black);
|
||||||
background-position: center;
|
text-shadow: 1px 1px rgba(0, 0, 0, .5);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nitro-camera-checkout {
|
||||||
|
width: 336px;
|
||||||
|
|
||||||
|
.picture-preview {
|
||||||
|
width: 320px;
|
||||||
|
height: 320px;
|
||||||
|
|
||||||
.slider {
|
.slider {
|
||||||
background: linear-gradient(180deg, transparent, black);
|
background: linear-gradient(180deg, transparent, black);
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
|
import { RoomWidgetCameraConfigurationComposer, RoomWidgetCameraConfigurationEvent } from 'nitro-renderer';
|
||||||
import { RoomCameraWidgetManagerEvent } from 'nitro-renderer/src/nitro/camera/events/RoomCameraWidgetManagerEvent';
|
import { RoomCameraWidgetManagerEvent } from 'nitro-renderer/src/nitro/camera/events/RoomCameraWidgetManagerEvent';
|
||||||
|
import { IRoomCameraWidgetSelectedEffect } from 'nitro-renderer/src/nitro/camera/IRoomCameraWidgetSelectedEffect';
|
||||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { IRoomCameraWidgetSelectedEffect } from '../../../../../../nitro-renderer/src/nitro/camera/IRoomCameraWidgetSelectedEffect';
|
|
||||||
import { GetRoomCameraWidgetManager } from '../../../../api';
|
import { GetRoomCameraWidgetManager } from '../../../../api';
|
||||||
import { RoomWidgetCameraEvent } from '../../../../events/room-widgets/camera/RoomWidgetCameraEvent';
|
import { RoomWidgetCameraEvent } from '../../../../events/room-widgets/camera/RoomWidgetCameraEvent';
|
||||||
import { useCameraEvent } from '../../../../hooks/events/nitro/camera/camera-event';
|
import { useCameraEvent } from '../../../../hooks/events/nitro/camera/camera-event';
|
||||||
import { useUiEvent } from '../../../../hooks/events/ui/ui-event';
|
import { useUiEvent } from '../../../../hooks/events/ui/ui-event';
|
||||||
|
import { CreateMessageHook, SendMessageHook } from '../../../../hooks/messages/message-event';
|
||||||
import { CameraWidgetViewProps } from './CameraWidgetView.types';
|
import { CameraWidgetViewProps } from './CameraWidgetView.types';
|
||||||
import { CameraWidgetContextProvider } from './context/CameraWidgetContext';
|
import { CameraWidgetContextProvider } from './context/CameraWidgetContext';
|
||||||
import { CameraWidgetCaptureView } from './views/capture/CameraWidgetCaptureView';
|
import { CameraWidgetCaptureView } from './views/capture/CameraWidgetCaptureView';
|
||||||
|
import { CameraWidgetCheckoutView } from './views/checkout/CameraWidgetCheckoutView';
|
||||||
import { CameraWidgetEditorView } from './views/editor/CameraWidgetEditorView';
|
import { CameraWidgetEditorView } from './views/editor/CameraWidgetEditorView';
|
||||||
|
|
||||||
export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const [ effectsReady, setEffectsReady ] = useState(false);
|
const [ effectsReady, setEffectsReady ] = useState(false);
|
||||||
|
|
||||||
const [ isCaptureVisible, setIsCaptureVisible ] = useState(false);
|
const [ isCaptureVisible, setIsCaptureVisible ] = useState(false);
|
||||||
const [ isEditorVisible, setIsEditorVisible ] = useState(false);
|
const [ isEditorVisible, setIsEditorVisible ] = useState(false);
|
||||||
|
const [ isCheckoutVisible, setIsCheckoutVisible ] = useState(false);
|
||||||
|
|
||||||
|
const [ myLevel, setMyLevel ] = useState(10);
|
||||||
const [ cameraRoll, setCameraRoll ] = useState<HTMLImageElement[]>([]);
|
const [ cameraRoll, setCameraRoll ] = useState<HTMLImageElement[]>([]);
|
||||||
const [ selectedPictureIndex, setSelectedPictureIndex ] = useState(-1);
|
const [ selectedPictureIndex, setSelectedPictureIndex ] = useState(-1);
|
||||||
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
|
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
|
||||||
|
const [ isZoomed, setIsZoomed ] = useState(false);
|
||||||
|
const [ price, setPrice ] = useState<{credits: Number, points: Number, pointsType: number}>(null);
|
||||||
|
|
||||||
const onNitroEvent = useCallback((event: RoomWidgetCameraEvent) =>
|
const onNitroEvent = useCallback((event: RoomWidgetCameraEvent) =>
|
||||||
{
|
{
|
||||||
@ -30,10 +38,12 @@ export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
|||||||
case RoomWidgetCameraEvent.HIDE_CAMERA:
|
case RoomWidgetCameraEvent.HIDE_CAMERA:
|
||||||
setIsCaptureVisible(false);
|
setIsCaptureVisible(false);
|
||||||
setIsEditorVisible(false);
|
setIsEditorVisible(false);
|
||||||
|
setIsCheckoutVisible(false);
|
||||||
return;
|
return;
|
||||||
case RoomWidgetCameraEvent.TOGGLE_CAMERA:
|
case RoomWidgetCameraEvent.TOGGLE_CAMERA:
|
||||||
setIsEditorVisible(false);
|
|
||||||
setIsCaptureVisible(value => !value);
|
setIsCaptureVisible(value => !value);
|
||||||
|
setIsEditorVisible(false);
|
||||||
|
setIsCheckoutVisible(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@ -42,6 +52,22 @@ export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
|||||||
useUiEvent(RoomWidgetCameraEvent.HIDE_CAMERA, onNitroEvent);
|
useUiEvent(RoomWidgetCameraEvent.HIDE_CAMERA, onNitroEvent);
|
||||||
useUiEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA, onNitroEvent);
|
useUiEvent(RoomWidgetCameraEvent.TOGGLE_CAMERA, onNitroEvent);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(price) return;
|
||||||
|
|
||||||
|
SendMessageHook(new RoomWidgetCameraConfigurationComposer());
|
||||||
|
}, [ price ]);
|
||||||
|
|
||||||
|
const onCameraConfigurationEvent = useCallback((event: RoomWidgetCameraConfigurationEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setPrice({ credits: parser.credits, points: parser.points, pointsType: parser.pointsType });
|
||||||
|
}, [ price ]);
|
||||||
|
|
||||||
|
CreateMessageHook(RoomWidgetCameraConfigurationEvent, onCameraConfigurationEvent);
|
||||||
|
|
||||||
const availableEffects = useMemo(() =>
|
const availableEffects = useMemo(() =>
|
||||||
{
|
{
|
||||||
if(!effectsReady) return null;
|
if(!effectsReady) return null;
|
||||||
@ -75,6 +101,7 @@ export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
|||||||
case 'close':
|
case 'close':
|
||||||
setIsCaptureVisible(false);
|
setIsCaptureVisible(false);
|
||||||
setIsEditorVisible(false);
|
setIsEditorVisible(false);
|
||||||
|
setIsCheckoutVisible(false);
|
||||||
return;
|
return;
|
||||||
case 'capture_edit':
|
case 'capture_edit':
|
||||||
setIsCaptureVisible(false);
|
setIsCaptureVisible(false);
|
||||||
@ -83,14 +110,20 @@ export const CameraWidgetView: FC<CameraWidgetViewProps> = props =>
|
|||||||
case 'editor_cancel':
|
case 'editor_cancel':
|
||||||
setIsCaptureVisible(true);
|
setIsCaptureVisible(true);
|
||||||
setIsEditorVisible(false);
|
setIsEditorVisible(false);
|
||||||
|
setIsCheckoutVisible(false);
|
||||||
|
return;
|
||||||
|
case 'editor_checkout':
|
||||||
|
setIsEditorVisible(false);
|
||||||
|
setIsCheckoutVisible(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CameraWidgetContextProvider value={ { cameraRoll, setCameraRoll, selectedPictureIndex, setSelectedPictureIndex, selectedEffects, setSelectedEffects } }>
|
<CameraWidgetContextProvider value={ { cameraRoll, setCameraRoll, selectedPictureIndex, setSelectedPictureIndex, selectedEffects, setSelectedEffects, isZoomed, setIsZoomed } }>
|
||||||
{ ( isCaptureVisible && <CameraWidgetCaptureView onCloseClick={ () => processAction('close') } onEditClick={ () => processAction('capture_edit') } /> ) ||
|
{ isCaptureVisible && <CameraWidgetCaptureView onCloseClick={ () => processAction('close') } onEditClick={ () => processAction('capture_edit') } /> }
|
||||||
( isEditorVisible && <CameraWidgetEditorView onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } availableEffects={ availableEffects } /> ) }
|
{ isEditorVisible && <CameraWidgetEditorView myLevel={ myLevel } onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } onCheckoutClick={ () => processAction('editor_checkout') } availableEffects={ availableEffects } /> }
|
||||||
|
{ isCheckoutVisible && <CameraWidgetCheckoutView onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } price={ price }></CameraWidgetCheckoutView> }
|
||||||
</CameraWidgetContextProvider>
|
</CameraWidgetContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ const CameraWidgetContext = createContext<ICameraWidgetContext>({
|
|||||||
selectedPictureIndex: null,
|
selectedPictureIndex: null,
|
||||||
setSelectedPictureIndex: null,
|
setSelectedPictureIndex: null,
|
||||||
selectedEffects: null,
|
selectedEffects: null,
|
||||||
setSelectedEffects: null
|
setSelectedEffects: null,
|
||||||
|
isZoomed: null,
|
||||||
|
setIsZoomed: null
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CameraWidgetContextProvider: FC<CameraWidgetContextProps> = props =>
|
export const CameraWidgetContextProvider: FC<CameraWidgetContextProps> = props =>
|
||||||
|
@ -8,7 +8,9 @@ export interface ICameraWidgetContext
|
|||||||
selectedPictureIndex: number,
|
selectedPictureIndex: number,
|
||||||
setSelectedPictureIndex: (index: number) => void,
|
setSelectedPictureIndex: (index: number) => void,
|
||||||
selectedEffects: IRoomCameraWidgetSelectedEffect[],
|
selectedEffects: IRoomCameraWidgetSelectedEffect[],
|
||||||
setSelectedEffects: (selectedEffects: IRoomCameraWidgetSelectedEffect[]) => void
|
setSelectedEffects: (selectedEffects: IRoomCameraWidgetSelectedEffect[]) => void,
|
||||||
|
isZoomed: boolean,
|
||||||
|
setIsZoomed: (isZoomed: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CameraWidgetContextProps extends ProviderProps<ICameraWidgetContext>
|
export interface CameraWidgetContextProps extends ProviderProps<ICameraWidgetContext>
|
||||||
|
@ -79,22 +79,22 @@ export const CameraWidgetCaptureView: FC<CameraWidgetCaptureViewProps> = props =
|
|||||||
<DraggableWindow handle=".nitro-camera-capture">
|
<DraggableWindow handle=".nitro-camera-capture">
|
||||||
<div className="nitro-camera-capture d-flex flex-column justify-content-center align-items-center">
|
<div className="nitro-camera-capture d-flex flex-column justify-content-center align-items-center">
|
||||||
<div className="camera-canvas">
|
<div className="camera-canvas">
|
||||||
<div className="overflow-auto">
|
<div className="nitro-card-close-parent">
|
||||||
<div className="cursor-pointer float-end me-3 mt-2" onClick={ event => processAction('close') }>
|
<div className="nitro-card-close" onClick={ event => processAction('close') }>
|
||||||
<i className="fas fa-times"></i>
|
<i className="fas fa-times"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref={ cameraFrameRef } className={'camera-frame ' + classNames({'bg': cameraWidgetContext.selectedPictureIndex > -1}) }>
|
<div ref={ cameraFrameRef } className={'camera-frame ' + classNames({'bg': cameraWidgetContext.selectedPictureIndex > -1}) }>
|
||||||
{ cameraWidgetContext.selectedPictureIndex > -1 && <div>
|
{ cameraWidgetContext.selectedPictureIndex > -1 && <div>
|
||||||
<img src={ cameraWidgetContext.cameraRoll[cameraWidgetContext.selectedPictureIndex].src } />
|
<img src={ cameraWidgetContext.cameraRoll[cameraWidgetContext.selectedPictureIndex].src } />
|
||||||
<div className="camera-frame-preview-actions w-100 position-absolute bottom-0 py-2 text-center">
|
<div className="camera-frame-preview-actions w-100 position-absolute bottom-0 py-2 text-center">
|
||||||
<button className="btn btn-success me-3" onClick={ event => processAction('edit_picture') }>{ LocalizeText('camera.editor.button.text') }</button>
|
<button className="btn btn-success me-3" title={ LocalizeText('camera.editor.button.tooltip') } onClick={ event => processAction('edit_picture') }>{ LocalizeText('camera.editor.button.text') }</button>
|
||||||
<button className="btn btn-danger" onClick={ event => processAction('discard_picture') }>{ LocalizeText('camera.delete.button.text') }</button>
|
<button className="btn btn-danger" onClick={ event => processAction('discard_picture') }>{ LocalizeText('camera.delete.button.text') }</button>
|
||||||
</div>
|
</div>
|
||||||
</div> }
|
</div> }
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex justify-content-center">
|
<div className="d-flex justify-content-center">
|
||||||
<div className="camera-button" onClick={ takePicture }></div>
|
<div className="camera-button" title={ LocalizeText('camera.take.photo.button.tooltip') } onClick={ takePicture }></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ cameraWidgetContext.cameraRoll.length > 0 && <div className="camera-roll d-flex justify-content-center py-2">
|
{ cameraWidgetContext.cameraRoll.length > 0 && <div className="camera-roll d-flex justify-content-center py-2">
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
import { RoomWidgetCameraPublishComposer, RoomWidgetCameraPublishedEvent, RoomWidgetCameraPurchaseComposer, RoomWidgetCameraPurchaseSuccessfulEvent } from 'nitro-renderer';
|
||||||
|
import { FC, useCallback, useState } from 'react';
|
||||||
|
import { GetRoomCameraWidgetManager } from '../../../../../../api/nitro/camera/GetRoomCameraWidgetManager';
|
||||||
|
import { CreateMessageHook, SendMessageHook } from '../../../../../../hooks/messages/message-event';
|
||||||
|
import { NitroCardContentView } from '../../../../../../layout/card/content/NitroCardContentView';
|
||||||
|
import { NitroCardView } from '../../../../../../layout/card/NitroCardView';
|
||||||
|
import { NitroCardSimpleHeaderView } from '../../../../../../layout/card/simple-header/NitroCardSimpleHeaderView';
|
||||||
|
import { LocalizeText } from '../../../../../../utils/LocalizeText';
|
||||||
|
import { CurrencyIcon } from '../../../../../currency-icon/CurrencyIcon';
|
||||||
|
import { useCameraWidgetContext } from '../../context/CameraWidgetContext';
|
||||||
|
import { CameraWidgetCheckoutViewProps } from './CameraWidgetCheckoutView.types';
|
||||||
|
|
||||||
|
export const CameraWidgetCheckoutView: FC<CameraWidgetCheckoutViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { onCloseClick = null, onCancelClick = null, price = null } = props;
|
||||||
|
|
||||||
|
const cameraWidgetContext = useCameraWidgetContext();
|
||||||
|
|
||||||
|
const [ picturesBought, setPicturesBought ] = useState(0);
|
||||||
|
const [ wasPicturePublished, setWasPicturePublished ] = useState(false);
|
||||||
|
const [ isWaiting, setIsWaiting ] = useState(false);
|
||||||
|
const [ publishCooldown, setPublishCooldown ] = useState(0);
|
||||||
|
|
||||||
|
const onCameraPurchaseSuccessfulEvent = useCallback((event: RoomWidgetCameraPurchaseSuccessfulEvent) =>
|
||||||
|
{
|
||||||
|
setPicturesBought(value => value + 1);
|
||||||
|
setIsWaiting(false);
|
||||||
|
}, [ picturesBought ]);
|
||||||
|
|
||||||
|
const onRoomWidgetCameraPublishedEvent = useCallback((event: RoomWidgetCameraPublishedEvent) =>
|
||||||
|
{
|
||||||
|
const parser = event.getParser();
|
||||||
|
|
||||||
|
setPublishCooldown(parser.cooldownSeconds);
|
||||||
|
setWasPicturePublished(parser.wasSuccessful);
|
||||||
|
setIsWaiting(false);
|
||||||
|
}, [ wasPicturePublished, publishCooldown ]);
|
||||||
|
|
||||||
|
CreateMessageHook(RoomWidgetCameraPurchaseSuccessfulEvent, onCameraPurchaseSuccessfulEvent);
|
||||||
|
CreateMessageHook(RoomWidgetCameraPublishedEvent, onRoomWidgetCameraPublishedEvent);
|
||||||
|
|
||||||
|
const getCurrentPicture = useCallback(() =>
|
||||||
|
{
|
||||||
|
return GetRoomCameraWidgetManager().applyEffects(cameraWidgetContext.cameraRoll[cameraWidgetContext.selectedPictureIndex], cameraWidgetContext.selectedEffects, cameraWidgetContext.isZoomed);
|
||||||
|
}, [ cameraWidgetContext.selectedEffects, cameraWidgetContext.isZoomed ]);
|
||||||
|
|
||||||
|
const processAction = useCallback((type: string, value: string | number = null) =>
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 'close':
|
||||||
|
onCloseClick();
|
||||||
|
return;
|
||||||
|
case 'buy':
|
||||||
|
if(isWaiting) return;
|
||||||
|
|
||||||
|
setIsWaiting(true);
|
||||||
|
SendMessageHook(new RoomWidgetCameraPurchaseComposer());
|
||||||
|
return;
|
||||||
|
case 'publish':
|
||||||
|
if(isWaiting) return;
|
||||||
|
|
||||||
|
setIsWaiting(true);
|
||||||
|
SendMessageHook(new RoomWidgetCameraPublishComposer());
|
||||||
|
return;
|
||||||
|
case 'cancel':
|
||||||
|
onCancelClick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, [ onCloseClick, onCancelClick ]);
|
||||||
|
|
||||||
|
if(!price) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NitroCardView className="nitro-camera-checkout">
|
||||||
|
<NitroCardSimpleHeaderView headerText={ LocalizeText('camera.confirm_phase.title') } onCloseClick={ event => processAction('close') } />
|
||||||
|
<NitroCardContentView>
|
||||||
|
<div className="picture-preview border mb-2" style={ { backgroundImage: 'url(' + getCurrentPicture().src + ')' } }></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>
|
||||||
|
<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>
|
||||||
|
</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.points > 0 && <>: { price.points } <CurrencyIcon type={ price.pointsType } /></> }</div>
|
||||||
|
<div>{ LocalizeText(wasPicturePublished ? 'camera.publish.success.short.info' : 'camera.publish.detailed.explanation') }</div>
|
||||||
|
{ wasPicturePublished && <a href="#">{ LocalizeText('camera.link.to.published') }</a> }
|
||||||
|
</div>
|
||||||
|
{ !wasPicturePublished && <button className="btn btn-success" disabled={ isWaiting || publishCooldown > 0 } onClick={ event => processAction('publish') }>{ LocalizeText('camera.publish.button.text') }</button> }
|
||||||
|
</div>
|
||||||
|
{ publishCooldown > 0 && <div className="mt-1 text-center fw-bold">{ LocalizeText('camera.publish.wait', ['minutes'], [Math.ceil(publishCooldown/60).toString()]) }</div> }
|
||||||
|
</div>
|
||||||
|
<div className="text-black mb-2 text-center">{ LocalizeText('camera.warning.disclaimer') }</div>
|
||||||
|
<div className="d-flex justify-content-end">
|
||||||
|
<button className="btn btn-primary" onClick={ event => processAction('cancel') }>{ LocalizeText('generic.cancel') }</button>
|
||||||
|
</div>
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
export interface CameraWidgetCheckoutViewProps
|
||||||
|
{
|
||||||
|
onCloseClick: () => void;
|
||||||
|
onCancelClick: () => void;
|
||||||
|
price: {credits: Number, points: Number, pointsType: number};
|
||||||
|
}
|
@ -13,17 +13,15 @@ import { CameraWidgetEditorTabs, CameraWidgetEditorViewProps } from './CameraWid
|
|||||||
|
|
||||||
export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { availableEffects = null, onCloseClick = null, onCancelClick = null } = props;
|
const { availableEffects = null, myLevel = null, onCloseClick = null, onCancelClick = null, onCheckoutClick = null } = props;
|
||||||
|
|
||||||
const TABS: string[] = [ CameraWidgetEditorTabs.COLORMATRIX, CameraWidgetEditorTabs.COMPOSITE ];
|
const TABS: string[] = [ CameraWidgetEditorTabs.COLORMATRIX, CameraWidgetEditorTabs.COMPOSITE ];
|
||||||
const MY_LEVEL: number = 6;
|
|
||||||
|
|
||||||
const cameraWidgetContext = useCameraWidgetContext();
|
const cameraWidgetContext = useCameraWidgetContext();
|
||||||
|
|
||||||
const [ currentTab, setCurrentTab ] = useState(CameraWidgetEditorTabs.COLORMATRIX);
|
const [ currentTab, setCurrentTab ] = useState(CameraWidgetEditorTabs.COLORMATRIX);
|
||||||
const [ selectedEffectName, setSelectedEffectName ] = useState(null);
|
const [ selectedEffectName, setSelectedEffectName ] = useState(null);
|
||||||
const [ effectsThumbnails, setEffectsThumbnails ] = useState<{ name: string, image: HTMLImageElement }[]>([]);
|
const [ effectsThumbnails, setEffectsThumbnails ] = useState<{ name: string, image: HTMLImageElement }[]>([]);
|
||||||
const [ isZoomed, setIsZoomed ] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -60,8 +58,8 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
|
|
||||||
const getCurrentPicture = useCallback(() =>
|
const getCurrentPicture = useCallback(() =>
|
||||||
{
|
{
|
||||||
return GetRoomCameraWidgetManager().applyEffects(cameraWidgetContext.cameraRoll[cameraWidgetContext.selectedPictureIndex], cameraWidgetContext.selectedEffects, isZoomed);
|
return GetRoomCameraWidgetManager().applyEffects(cameraWidgetContext.cameraRoll[cameraWidgetContext.selectedPictureIndex], cameraWidgetContext.selectedEffects, cameraWidgetContext.isZoomed);
|
||||||
}, [ cameraWidgetContext.selectedEffects, isZoomed ]);
|
}, [ cameraWidgetContext.selectedEffects, cameraWidgetContext.isZoomed ]);
|
||||||
|
|
||||||
const getCurrentEffectAlpha = useCallback(() =>
|
const getCurrentEffectAlpha = useCallback(() =>
|
||||||
{
|
{
|
||||||
@ -106,6 +104,9 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
case 'cancel':
|
case 'cancel':
|
||||||
onCancelClick();
|
onCancelClick();
|
||||||
return;
|
return;
|
||||||
|
case 'checkout':
|
||||||
|
onCheckoutClick();
|
||||||
|
return;
|
||||||
case 'change_tab':
|
case 'change_tab':
|
||||||
setCurrentTab(String(value));
|
setCurrentTab(String(value));
|
||||||
return;
|
return;
|
||||||
@ -124,12 +125,12 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
{
|
{
|
||||||
effect = availableEffects.find(effect => effect.name === value);
|
effect = availableEffects.find(effect => effect.name === value);
|
||||||
|
|
||||||
if(effect.minLevel > MY_LEVEL) return;
|
if(effect.minLevel > myLevel) return;
|
||||||
|
|
||||||
cameraWidgetContext.setSelectedEffects([...cameraWidgetContext.selectedEffects, new RoomCameraWidgetSelectedEffect(effect, 0.5)]);
|
cameraWidgetContext.setSelectedEffects([...cameraWidgetContext.selectedEffects, new RoomCameraWidgetSelectedEffect(effect, 0.5)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(effect && effect.minLevel > MY_LEVEL) return;
|
if(effect && effect.minLevel > myLevel) return;
|
||||||
|
|
||||||
if(selectedEffectName !== value)
|
if(selectedEffectName !== value)
|
||||||
{
|
{
|
||||||
@ -169,7 +170,7 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
window.open(getCurrentPicture().src, '_blank');
|
window.open(getCurrentPicture().src, '_blank');
|
||||||
return;
|
return;
|
||||||
case 'zoom':
|
case 'zoom':
|
||||||
setIsZoomed(isZoomed => !isZoomed);
|
cameraWidgetContext.setIsZoomed(!cameraWidgetContext.isZoomed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [ onCloseClick, onCancelClick, availableEffects, cameraWidgetContext.selectedEffects, selectedEffectName ]);
|
}, [ onCloseClick, onCancelClick, availableEffects, cameraWidgetContext.selectedEffects, selectedEffectName ]);
|
||||||
@ -193,11 +194,11 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
return (
|
return (
|
||||||
<div key={ effect.name } className="col mb-3 position-relative">
|
<div key={ effect.name } className="col mb-3 position-relative">
|
||||||
{ getEffectIndex(effect.name) > -1 && <button className="btn btn-danger btn-sm p-0 position-absolute btn-remove-effect" onClick={ event => processAction('remove_effect', effect.name) }><i className="fas fa-times"></i></button> }
|
{ getEffectIndex(effect.name) > -1 && <button className="btn btn-danger btn-sm p-0 position-absolute btn-remove-effect" onClick={ event => processAction('remove_effect', effect.name) }><i className="fas fa-times"></i></button> }
|
||||||
<div title={ effect.minLevel <= MY_LEVEL ? LocalizeText('camera.effect.name.' + effect.name) : LocalizeText('camera.effect.required.level') + ' ' + effect.minLevel } onClick={ event => processAction('select_effect', effect.name) } className={"effect-thumbnail cursor-pointer position-relative border border-2 rounded d-flex flex-column justify-content-center align-items-center py-1" + classNames({' active': selectedEffectName === effect.name})}>
|
<div title={ effect.minLevel <= myLevel ? LocalizeText('camera.effect.name.' + effect.name) : LocalizeText('camera.effect.required.level') + ' ' + effect.minLevel } onClick={ event => processAction('select_effect', effect.name) } className={"effect-thumbnail cursor-pointer position-relative border border-2 rounded d-flex flex-column justify-content-center align-items-center py-1" + classNames({' active': selectedEffectName === effect.name})}>
|
||||||
{ effect.minLevel <= MY_LEVEL && <div className="effect-thumbnail-image border">
|
{ effect.minLevel <= myLevel && <div className="effect-thumbnail-image border">
|
||||||
<img alt="" src={ getEffectThumbnail(effect.name) } />
|
<img alt="" src={ getEffectThumbnail(effect.name) } />
|
||||||
</div> }
|
</div> }
|
||||||
{ effect.minLevel > MY_LEVEL && <div className="text-center text-black">
|
{ effect.minLevel > myLevel && <div className="text-center text-black">
|
||||||
<div><i className="fas fa-lock"></i></div>
|
<div><i className="fas fa-lock"></i></div>
|
||||||
<div className="fw-bold">{ effect.minLevel }</div>
|
<div className="fw-bold">{ effect.minLevel }</div>
|
||||||
</div> }
|
</div> }
|
||||||
@ -212,7 +213,7 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
<div className="w-100">
|
<div className="w-100">
|
||||||
<NitroCardTabsView></NitroCardTabsView>
|
<NitroCardTabsView></NitroCardTabsView>
|
||||||
<NitroCardContentView>
|
<NitroCardContentView>
|
||||||
<div className="d-flex align-items-end picture-preview" style={ { backgroundImage: 'url(' + getCurrentPicture().src + ')' } }>
|
<div className="d-flex align-items-end picture-preview border" style={ { backgroundImage: 'url(' + getCurrentPicture().src + ')' } }>
|
||||||
{ selectedEffectName && <div className="w-100 p-2 d-flex flex-column justify-content-center slider">
|
{ selectedEffectName && <div className="w-100 p-2 d-flex flex-column justify-content-center slider">
|
||||||
<div className="w-100 text-center">{ LocalizeText('camera.effect.name.' + selectedEffectName) + ' - ' + getCurrentEffectAlpha() }</div>
|
<div className="w-100 text-center">{ LocalizeText('camera.effect.name.' + selectedEffectName) + ' - ' + getCurrentEffectAlpha() }</div>
|
||||||
<input type="range" min="0" max="1" step="0.01" value={ getCurrentEffectAlpha() } onChange={ event => setSelectedEffectAlpha(Number(event.target.value)) } className="form-range w-100" />
|
<input type="range" min="0" max="1" step="0.01" value={ getCurrentEffectAlpha() } onChange={ event => setSelectedEffectAlpha(Number(event.target.value)) } className="form-range w-100" />
|
||||||
@ -222,11 +223,11 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
|||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
<button className="btn btn-primary" onClick={ event => processAction('clear_effects') }><i className="fas fa-trash"></i></button>
|
<button className="btn btn-primary" onClick={ event => processAction('clear_effects') }><i className="fas fa-trash"></i></button>
|
||||||
<button className="btn btn-primary" onClick={ event => processAction('download') }><i className="fas fa-save"></i></button>
|
<button className="btn btn-primary" onClick={ event => processAction('download') }><i className="fas fa-save"></i></button>
|
||||||
<button className="btn btn-primary" onClick={ event => processAction('zoom') }><i className={"fas " + classNames({'fa-search-plus': !isZoomed, 'fa-search-minus': isZoomed})}></i></button>
|
<button className="btn btn-primary" onClick={ event => processAction('zoom') }><i className={"fas " + classNames({'fa-search-plus': !cameraWidgetContext.isZoomed, 'fa-search-minus': cameraWidgetContext.isZoomed})}></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex justify-content-end">
|
<div className="d-flex justify-content-end">
|
||||||
<button className="btn btn-primary me-2" onClick={ event => processAction('cancel') }>{ LocalizeText('generic.cancel') }</button>
|
<button className="btn btn-primary me-2" onClick={ event => processAction('cancel') }>{ LocalizeText('generic.cancel') }</button>
|
||||||
<button className="btn btn-success">{ LocalizeText('camera.preview.button.text') }</button>
|
<button className="btn btn-success" onClick={ event => processAction('checkout') }>{ LocalizeText('camera.preview.button.text') }</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</NitroCardContentView>
|
</NitroCardContentView>
|
||||||
|
@ -3,8 +3,10 @@ import { IRoomCameraWidgetEffect } from 'nitro-renderer/src/nitro/camera/IRoomCa
|
|||||||
export interface CameraWidgetEditorViewProps
|
export interface CameraWidgetEditorViewProps
|
||||||
{
|
{
|
||||||
availableEffects: IRoomCameraWidgetEffect[];
|
availableEffects: IRoomCameraWidgetEffect[];
|
||||||
|
myLevel: number;
|
||||||
onCloseClick: () => void;
|
onCloseClick: () => void;
|
||||||
onCancelClick: () => void;
|
onCancelClick: () => void;
|
||||||
|
onCheckoutClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CameraWidgetEditorTabs
|
export class CameraWidgetEditorTabs
|
||||||
|
Loading…
Reference in New Issue
Block a user