mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-22 22:30:52 +01:00
More camera changes
This commit is contained in:
parent
47c0ab6c44
commit
a3350b8b54
@ -87,6 +87,53 @@
|
||||
.nitro-camera-editor {
|
||||
width: 600px;
|
||||
|
||||
.content-area {
|
||||
min-height: 350px;
|
||||
height: 350px;
|
||||
resize: vertical;
|
||||
|
||||
.picture-preview {
|
||||
width: 320px;
|
||||
height: 320px;
|
||||
|
||||
.slider {
|
||||
background: linear-gradient(180deg, transparent, black);
|
||||
text-shadow: 1px 1px rgba(0, 0, 0, .5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.effect-grid {
|
||||
|
||||
.grid-item-container {
|
||||
height: 60px !important;
|
||||
max-height: 60px !important;
|
||||
|
||||
.grid-item {
|
||||
overflow: unset;
|
||||
|
||||
.remove-effect {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
padding: 2px;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
min-height: unset;
|
||||
}
|
||||
|
||||
.effect-thumbnail-image {
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
image-rendering: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.effects {
|
||||
height: 363px;
|
||||
min-height: 363px;
|
||||
@ -117,16 +164,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.picture-preview {
|
||||
width: 320px;
|
||||
height: 320px;
|
||||
|
||||
.slider {
|
||||
background: linear-gradient(180deg, transparent, black);
|
||||
text-shadow: 1px 1px rgba(0, 0, 0, .5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nitro-camera-checkout {
|
||||
|
@ -24,7 +24,7 @@ export const CameraWidgetView: FC<{}> = props =>
|
||||
const [ selectedPictureIndex, setSelectedPictureIndex ] = useState(-1);
|
||||
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
|
||||
const [ isZoomed, setIsZoomed ] = useState(false);
|
||||
const [ myLevel, setMyLevel ] = useState(10);
|
||||
const [ myLevel, setMyLevel ] = useState(1);
|
||||
const [ price, setPrice ] = useState<{ credits: number, duckets: number, publishDucketPrice: number }>(null);
|
||||
|
||||
const onNitroEvent = useCallback((event: RoomWidgetCameraEvent) =>
|
||||
@ -111,7 +111,7 @@ export const CameraWidgetView: FC<{}> = props =>
|
||||
return (
|
||||
<CameraWidgetContextProvider value={ { cameraRoll, setCameraRoll, selectedPictureIndex, setSelectedPictureIndex, selectedEffects, setSelectedEffects, isZoomed, setIsZoomed } }>
|
||||
{ (mode === MODE_CAPTURE) && <CameraWidgetCaptureView onClose={ () => processAction('close') } onEdit={ () => processAction('edit') } onDelete={ () => processAction('delete') } /> }
|
||||
{ (mode === MODE_EDITOR) && <CameraWidgetEditorView myLevel={ myLevel } onClose={ () => processAction('close') } onCancel={ () => processAction('editor_cancel') } onCheckout={ () => processAction('checkout') } availableEffects={ availableEffects } /> }
|
||||
{ (mode === MODE_EDITOR) && <CameraWidgetEditorView picture={ cameraRoll[selectedPictureIndex] } myLevel={ myLevel } onClose={ () => processAction('close') } onCancel={ () => processAction('editor_cancel') } onCheckout={ () => processAction('checkout') } availableEffects={ availableEffects } /> }
|
||||
{ (mode === MODE_CHECKOUT) && <CameraWidgetCheckoutView onCloseClick={ () => processAction('close') } onCancelClick={ () => processAction('editor_cancel') } price={ price }></CameraWidgetCheckoutView> }
|
||||
</CameraWidgetContextProvider>
|
||||
);
|
||||
|
@ -0,0 +1,6 @@
|
||||
export class CameraPictureThumbnail
|
||||
{
|
||||
constructor(
|
||||
public effectName: string,
|
||||
public thumbnailUrl: string) {}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
import { IRoomCameraWidgetSelectedEffect } from '@nitrots/nitro-renderer';
|
||||
import { ProviderProps } from 'react';
|
||||
import { Dispatch, ProviderProps, SetStateAction } from 'react';
|
||||
import { CameraPicture } from '../common/CameraPicture';
|
||||
|
||||
export interface ICameraWidgetContext
|
||||
{
|
||||
cameraRoll: CameraPicture[],
|
||||
setCameraRoll: (cameraRoll: CameraPicture[]) => void,
|
||||
setCameraRoll: Dispatch<SetStateAction<CameraPicture[]>>;
|
||||
selectedPictureIndex: number,
|
||||
setSelectedPictureIndex: (index: number) => void,
|
||||
setSelectedPictureIndex: Dispatch<SetStateAction<number>>;
|
||||
selectedEffects: IRoomCameraWidgetSelectedEffect[],
|
||||
setSelectedEffects: (selectedEffects: IRoomCameraWidgetSelectedEffect[]) => void,
|
||||
setSelectedEffects: Dispatch<SetStateAction<IRoomCameraWidgetSelectedEffect[]>>;
|
||||
isZoomed: boolean,
|
||||
setIsZoomed: (isZoomed: boolean) => void
|
||||
setIsZoomed: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export interface CameraWidgetContextProps extends ProviderProps<ICameraWidgetContext>
|
||||
|
@ -1,94 +1,85 @@
|
||||
import { RoomCameraWidgetSelectedEffect } from '@nitrots/nitro-renderer';
|
||||
import classNames from 'classnames';
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { IRoomCameraWidgetSelectedEffect, RoomCameraWidgetSelectedEffect } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { GetRoomCameraWidgetManager } from '../../../../../../api';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../../../layout';
|
||||
import { LocalizeText } from '../../../../../../utils/LocalizeText';
|
||||
import { useCameraWidgetContext } from '../../context/CameraWidgetContext';
|
||||
import { CameraPictureThumbnail } from '../../common/CameraPictureThumbnail';
|
||||
import { CameraWidgetEditorTabs, CameraWidgetEditorViewProps } from './CameraWidgetEditorView.types';
|
||||
import { CameraWidgetEffectListView } from './effect-list/CameraWidgetEffectListView';
|
||||
|
||||
const TABS: string[] = [ CameraWidgetEditorTabs.COLORMATRIX, CameraWidgetEditorTabs.COMPOSITE ];
|
||||
|
||||
export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
||||
{
|
||||
const { availableEffects = null, myLevel = 1, onClose = null, onCancel = null, onCheckout = null } = props;
|
||||
const { picture = null, availableEffects = null, myLevel = 1, onClose = null, onCancel = null, onCheckout = null } = props;
|
||||
const [ currentTab, setCurrentTab ] = useState(TABS[0]);
|
||||
const [ selectedEffectName, setSelectedEffectName ] = useState(null);
|
||||
const [ effectsThumbnails, setEffectsThumbnails ] = useState<{ name: string, image: HTMLImageElement }[]>([]);
|
||||
const { cameraRoll = null, selectedPictureIndex = -1, selectedEffects = null, isZoomed = false, setSelectedEffects = null, setIsZoomed = null } = useCameraWidgetContext();
|
||||
const [ selectedEffectName, setSelectedEffectName ] = useState<string>(null);
|
||||
const [ selectedEffects, setSelectedEffects ] = useState<IRoomCameraWidgetSelectedEffect[]>([]);
|
||||
const [ effectsThumbnails, setEffectsThumbnails ] = useState<CameraPictureThumbnail[]>([]);
|
||||
const [ isZoomed, setIsZoomed ] = useState(false);
|
||||
|
||||
useEffect(() =>
|
||||
const getColorMatrixEffects = useMemo(() =>
|
||||
{
|
||||
const thumbnails = [];
|
||||
return availableEffects.filter(effect => effect.colorMatrix);
|
||||
}, [ availableEffects ]);
|
||||
|
||||
for(const effect of availableEffects)
|
||||
{
|
||||
thumbnails.push({name: effect.name, image: GetRoomCameraWidgetManager().applyEffects(cameraRoll[selectedPictureIndex].texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false)});
|
||||
}
|
||||
|
||||
setEffectsThumbnails(thumbnails);
|
||||
}, [ cameraRoll, selectedPictureIndex, availableEffects ]);
|
||||
|
||||
const getEffectThumbnail = useCallback((effectName: string) =>
|
||||
const getCompositeEffects = useMemo(() =>
|
||||
{
|
||||
const search = effectsThumbnails.find(thumbnail => thumbnail.name === effectName);
|
||||
|
||||
if(search) return search.image.src;
|
||||
|
||||
return null;
|
||||
}, [ effectsThumbnails ]);
|
||||
return availableEffects.filter(effect => effect.texture);
|
||||
}, [ availableEffects ]);
|
||||
|
||||
const getEffectList = useCallback(() =>
|
||||
{
|
||||
if(currentTab === CameraWidgetEditorTabs.COLORMATRIX)
|
||||
{
|
||||
return availableEffects.filter(effect => effect.colorMatrix);
|
||||
return getColorMatrixEffects;
|
||||
}
|
||||
else
|
||||
{
|
||||
return availableEffects.filter(effect => effect.texture);
|
||||
}
|
||||
}, [ currentTab, availableEffects ]);
|
||||
|
||||
const getCurrentPicture = useCallback(() =>
|
||||
return getCompositeEffects;
|
||||
}, [ currentTab, getColorMatrixEffects, getCompositeEffects ]);
|
||||
|
||||
const getSelectedEffectIndex = useCallback((name: string) =>
|
||||
{
|
||||
return GetRoomCameraWidgetManager().applyEffects(cameraRoll[selectedPictureIndex].texture, selectedEffects, isZoomed);
|
||||
}, [ cameraRoll, selectedPictureIndex, selectedEffects, isZoomed ]);
|
||||
if(!name || !name.length || !selectedEffects || !selectedEffects.length) return -1;
|
||||
|
||||
const getCurrentEffectAlpha = useCallback(() =>
|
||||
{
|
||||
if(!selectedEffectName) return 0;
|
||||
|
||||
const selectedEffect = selectedEffects.find(effect => effect.effect.name === selectedEffectName);
|
||||
|
||||
if(!selectedEffect) return 0;
|
||||
|
||||
return selectedEffect.alpha;
|
||||
}, [ selectedEffectName, selectedEffects ]);
|
||||
|
||||
const getEffectIndex = useCallback((effectName) =>
|
||||
{
|
||||
return selectedEffects.findIndex(effect => effect.effect.name === effectName);
|
||||
return selectedEffects.findIndex(effect => (effect.effect.name === name));
|
||||
}, [ selectedEffects ])
|
||||
|
||||
const setSelectedEffectAlpha = useCallback((newAlpha: number) =>
|
||||
const getCurrentEffectIndex = useMemo(() =>
|
||||
{
|
||||
if(!selectedEffectName) return;
|
||||
return getSelectedEffectIndex(selectedEffectName)
|
||||
}, [ selectedEffectName, getSelectedEffectIndex ])
|
||||
|
||||
const selectedEffectIndex = getEffectIndex(selectedEffectName);
|
||||
const getCurrentEffect = useMemo(() =>
|
||||
{
|
||||
if(!selectedEffectName) return null;
|
||||
|
||||
if(selectedEffectIndex === -1) return;
|
||||
return (selectedEffects[getCurrentEffectIndex] || null);
|
||||
}, [ selectedEffectName, getCurrentEffectIndex, selectedEffects ]);
|
||||
|
||||
const clone = Array.from(selectedEffects);
|
||||
const setCurrentEffectAlpha = useCallback((alpha: number) =>
|
||||
{
|
||||
const index = getCurrentEffectIndex;
|
||||
|
||||
const selectedEffect = clone[selectedEffectIndex];
|
||||
if(index === -1) return;
|
||||
|
||||
clone[selectedEffectIndex] = new RoomCameraWidgetSelectedEffect(selectedEffect.effect, newAlpha);
|
||||
setSelectedEffects(prevValue =>
|
||||
{
|
||||
const clone = [ ...prevValue ];
|
||||
const currentEffect = clone[index];
|
||||
|
||||
setSelectedEffects(clone);
|
||||
}, [ selectedEffectName, getEffectIndex, selectedEffects, setSelectedEffects ]);
|
||||
clone[getCurrentEffectIndex] = new RoomCameraWidgetSelectedEffect(currentEffect.effect, alpha);
|
||||
|
||||
const processAction = useCallback((type: string, value: string | number = null) =>
|
||||
return clone;
|
||||
});
|
||||
}, [ getCurrentEffectIndex, setSelectedEffects ]);
|
||||
|
||||
const getCurrentPictureUrl = useMemo(() =>
|
||||
{
|
||||
return GetRoomCameraWidgetManager().applyEffects(picture.texture, selectedEffects, isZoomed).src;
|
||||
}, [ picture, selectedEffects, isZoomed ]);
|
||||
|
||||
const processAction = useCallback((type: string, effectName: string = null) =>
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
@ -102,131 +93,88 @@ export const CameraWidgetEditorView: FC<CameraWidgetEditorViewProps> = props =>
|
||||
onCheckout();
|
||||
return;
|
||||
case 'change_tab':
|
||||
setCurrentTab(String(value));
|
||||
setCurrentTab(String(effectName));
|
||||
return;
|
||||
case 'select_effect':
|
||||
{
|
||||
let existingIndex = -1;
|
||||
case 'select_effect': {
|
||||
let existingIndex = getSelectedEffectIndex(effectName);
|
||||
|
||||
if(selectedEffects.length > 0)
|
||||
{
|
||||
existingIndex = getEffectIndex(value);
|
||||
}
|
||||
|
||||
let effect = null;
|
||||
if(existingIndex >= 0) return;
|
||||
|
||||
const effect = availableEffects.find(effect => (effect.name === effectName));
|
||||
|
||||
if(existingIndex === -1)
|
||||
{
|
||||
effect = availableEffects.find(effect => effect.name === value);
|
||||
|
||||
if(effect.minLevel > myLevel) return;
|
||||
|
||||
setSelectedEffects([...selectedEffects, new RoomCameraWidgetSelectedEffect(effect, 0.5)]);
|
||||
}
|
||||
|
||||
if(effect && effect.minLevel > myLevel) return;
|
||||
if(!effect) return;
|
||||
|
||||
if(selectedEffectName !== value)
|
||||
setSelectedEffects(prevValue =>
|
||||
{
|
||||
setSelectedEffectName(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectedEffectName(null);
|
||||
}
|
||||
}
|
||||
return [ ...prevValue, new RoomCameraWidgetSelectedEffect(effect, 1) ];
|
||||
});
|
||||
|
||||
setSelectedEffectName(effect.name);
|
||||
return;
|
||||
case 'remove_effect':
|
||||
{
|
||||
const existingIndex = getEffectIndex(value);
|
||||
}
|
||||
case 'remove_effect': {
|
||||
let existingIndex = getSelectedEffectIndex(effectName);
|
||||
|
||||
if(existingIndex > -1)
|
||||
if(existingIndex === -1) return;
|
||||
|
||||
setSelectedEffects(prevValue =>
|
||||
{
|
||||
const effect = selectedEffects[existingIndex];
|
||||
const clone = [ ...prevValue ];
|
||||
|
||||
if(effect.effect.name === selectedEffectName)
|
||||
{
|
||||
setSelectedEffectName(null);
|
||||
}
|
||||
|
||||
const clone = Array.from(selectedEffects);
|
||||
clone.splice(existingIndex, 1);
|
||||
|
||||
setSelectedEffects(clone);
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
});
|
||||
|
||||
if(selectedEffectName === effectName) setSelectedEffectName(null);
|
||||
return;
|
||||
}
|
||||
case 'clear_effects':
|
||||
setSelectedEffectName(null);
|
||||
setSelectedEffects([]);
|
||||
return;
|
||||
case 'download':
|
||||
window.open(getCurrentPicture().src, '_blank');
|
||||
//window.open(getCurrentPicture().src, '_blank');
|
||||
return;
|
||||
case 'zoom':
|
||||
setIsZoomed(!isZoomed);
|
||||
return;
|
||||
}
|
||||
}, [ onClose, onCancel, onCheckout, getCurrentPicture, myLevel, selectedEffectName, getEffectIndex, availableEffects, isZoomed, setIsZoomed, selectedEffects, setSelectedEffects ]);
|
||||
}, [ isZoomed, availableEffects, getSelectedEffectIndex, selectedEffectName, onCancel, onCheckout, onClose, setIsZoomed, setSelectedEffects ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const thumbnails: CameraPictureThumbnail[] = [];
|
||||
|
||||
for(const effect of availableEffects)
|
||||
{
|
||||
thumbnails.push(new CameraPictureThumbnail(effect.name, GetRoomCameraWidgetManager().applyEffects(picture.texture, [ new RoomCameraWidgetSelectedEffect(effect, 1) ], false).src));
|
||||
}
|
||||
|
||||
setEffectsThumbnails(thumbnails);
|
||||
}, [ picture, availableEffects ]);
|
||||
|
||||
return (
|
||||
<NitroCardView className="nitro-camera-editor">
|
||||
<NitroCardHeaderView headerText={ LocalizeText('camera.editor.button.text') } onCloseClick={ event => processAction('close') } />
|
||||
<div className="d-flex">
|
||||
<div className="w-100">
|
||||
<NitroCardTabsView>
|
||||
{ TABS.map(tab =>
|
||||
{
|
||||
return <NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ event => processAction('change_tab', tab) }><i className={ 'icon icon-camera-' + tab }></i></NitroCardTabsItemView>
|
||||
}) }
|
||||
</NitroCardTabsView>
|
||||
<NitroCardContentView>
|
||||
<div className="d-flex h-100 overflow-auto effects px-2">
|
||||
<div className="row row-cols-3">
|
||||
{ getEffectList().map(effect =>
|
||||
{
|
||||
return (
|
||||
<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> }
|
||||
<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 <= myLevel && <div className="effect-thumbnail-image border">
|
||||
<img alt="" src={ getEffectThumbnail(effect.name) } />
|
||||
</div> }
|
||||
{ effect.minLevel > myLevel && <div className="text-center text-black">
|
||||
<div><i className="fas fa-lock"></i></div>
|
||||
<div className="fw-bold">{ effect.minLevel }</div>
|
||||
</div> }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
<NitroCardTabsView>
|
||||
{ TABS.map(tab =>
|
||||
{
|
||||
return <NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ event => processAction('change_tab', tab) }><i className={ 'icon icon-camera-' + tab }></i></NitroCardTabsItemView>
|
||||
}) }
|
||||
</NitroCardTabsView>
|
||||
<NitroCardContentView>
|
||||
<div className="row h-100">
|
||||
<div className="col-5 d-flex flex-column h-100">
|
||||
<CameraWidgetEffectListView myLevel={ myLevel } selectedEffects={ selectedEffects } effects={ getEffectList() } thumbnails={ effectsThumbnails } processAction={ processAction } />
|
||||
</div>
|
||||
<div className="col-7 d-flex flex-column h-100">
|
||||
<div className="picture-preview">
|
||||
<img alt="" src={ getCurrentPictureUrl } />
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<NitroCardTabsView></NitroCardTabsView>
|
||||
<NitroCardContentView>
|
||||
<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">
|
||||
<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" />
|
||||
</div> }
|
||||
</div>
|
||||
<div className="d-flex justify-content-between mt-2">
|
||||
<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('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>
|
||||
</div>
|
||||
<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-success" onClick={ event => processAction('checkout') }>{ LocalizeText('camera.preview.button.text') }</button>
|
||||
</div>
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
</div>
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { IRoomCameraWidgetEffect } from '@nitrots/nitro-renderer';
|
||||
import { CameraPicture } from '../../common/CameraPicture';
|
||||
|
||||
export interface CameraWidgetEditorViewProps
|
||||
{
|
||||
picture: CameraPicture;
|
||||
availableEffects: IRoomCameraWidgetEffect[];
|
||||
myLevel: number;
|
||||
onClose: () => void;
|
||||
|
@ -0,0 +1,29 @@
|
||||
import { FC } from 'react';
|
||||
import { NitroCardGridItemView } from '../../../../../../../layout/card/grid/item/NitroCardGridItemView';
|
||||
import { LocalizeText } from '../../../../../../../utils';
|
||||
import { CameraWidgetEffectListItemViewProps } from './CameraWidgetEffectListItemView.types';
|
||||
|
||||
export const CameraWidgetEffectListItemView: FC<CameraWidgetEffectListItemViewProps> = props =>
|
||||
{
|
||||
const { effect = null, thumbnailUrl = null, isActive = false, isLocked = false, selectEffect = null, removeEffect = null } = props;
|
||||
|
||||
return (
|
||||
<NitroCardGridItemView title={ LocalizeText(!isLocked ? (`camera.effect.name.${ effect.name }`) : `camera.effect.required.level ${ effect.minLevel }`) } itemActive={ isActive } onClick={ event => (!isActive && selectEffect()) }>
|
||||
{ isActive &&
|
||||
<button className="btn btn-danger btn-sm rounded-circle remove-effect" onClick={ removeEffect }>
|
||||
<i className="fas fa-times" />
|
||||
</button> }
|
||||
{ !isLocked && (thumbnailUrl && thumbnailUrl.length > 0) &&
|
||||
<div className="effect-thumbnail-image border">
|
||||
<img alt="" src={ thumbnailUrl } />
|
||||
</div> }
|
||||
{ isLocked &&
|
||||
<div className="text-center text-black">
|
||||
<div>
|
||||
<i className="fas fa-lock" />
|
||||
</div>
|
||||
<div className="fw-bold">{ effect.minLevel }</div>
|
||||
</div> }
|
||||
</NitroCardGridItemView>
|
||||
);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { IRoomCameraWidgetEffect } from '@nitrots/nitro-renderer';
|
||||
|
||||
export interface CameraWidgetEffectListItemViewProps
|
||||
{
|
||||
effect: IRoomCameraWidgetEffect;
|
||||
thumbnailUrl: string;
|
||||
isActive: boolean;
|
||||
isLocked: boolean;
|
||||
selectEffect: () => void;
|
||||
removeEffect: () => void;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { FC } from 'react';
|
||||
import { NitroCardGridView } from '../../../../../../../layout/card/grid/NitroCardGridView';
|
||||
import { CameraWidgetEffectListItemView } from '../effect-list-item/CameraWidgetEffectListItemView';
|
||||
import { CameraWidgetEffectListViewProps } from './CameraWidgetEffectListView.types';
|
||||
|
||||
export const CameraWidgetEffectListView: FC<CameraWidgetEffectListViewProps> = props =>
|
||||
{
|
||||
const { myLevel = 0, selectedEffects = [], effects = [], thumbnails = [], processAction = null } = props;
|
||||
|
||||
return (
|
||||
<NitroCardGridView className="effect-grid" columns={ 3 }>
|
||||
{ effects && (effects.length > 0) && effects.map((effect, index) =>
|
||||
{
|
||||
const thumbnailUrl = (thumbnails.find(thumbnail => (thumbnail.effectName === effect.name)));
|
||||
const isActive = (selectedEffects.findIndex(selectedEffect => (selectedEffect.effect.name === effect.name)) > -1);
|
||||
|
||||
return <CameraWidgetEffectListItemView key={ index } effect={ effect } thumbnailUrl={ ((thumbnailUrl && thumbnailUrl.thumbnailUrl) || null) } isActive={ isActive } isLocked={ (effect.minLevel > myLevel) } selectEffect={ () => processAction('select_effect', effect.name) } removeEffect={ () => processAction('remove_effect', effect.name) } />
|
||||
}) }
|
||||
</NitroCardGridView>
|
||||
);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { IRoomCameraWidgetEffect, IRoomCameraWidgetSelectedEffect } from '@nitrots/nitro-renderer';
|
||||
import { CameraPictureThumbnail } from '../../../common/CameraPictureThumbnail';
|
||||
|
||||
export interface CameraWidgetEffectListViewProps
|
||||
{
|
||||
myLevel: number;
|
||||
selectedEffects: IRoomCameraWidgetSelectedEffect[];
|
||||
effects: IRoomCameraWidgetEffect[];
|
||||
thumbnails: CameraPictureThumbnail[];
|
||||
processAction: (type: string, name: string) => void;
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
"src",
|
||||
"node_modules/@nitrots/nitro-renderer/src/**/*.ts",
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user