web-apps/apps/presentationeditor/mobile/src/view/edit/EditSlide.jsx
2021-10-25 11:19:50 +03:00

480 lines
22 KiB
JavaScript

import React, {Fragment, useEffect, useState} from 'react';
import {observer, inject} from "mobx-react";
import {f7, Page, Navbar, List, ListItem, Row, BlockTitle, Link, Toggle, Icon, View, NavRight, ListItemCell, Range, Button, Segmented, ListButton} from 'framework7-react';
import { ThemeColorPalette, CustomColorPicker } from '../../../../../common/mobile/lib/component/ThemeColorPalette.jsx';
import { useTranslation } from 'react-i18next';
import {Device} from '../../../../../common/mobile/utils/device';
import { element } from 'prop-types';
const EditSlide = props => {
const { t } = useTranslation();
const _t = t('View.Edit', {returnObjects: true});
return (
<Fragment>
<List>
<ListItem title={_t.textTheme} link="/theme/" routeProps={{
onThemeClick: props.onThemeClick
}}></ListItem>
<ListItem title={_t.textLayout} link="/layout/" routeProps={{
onLayoutClick: props.onLayoutClick
}}></ListItem>
<ListItem title={t('View.Edit.textTransitions')} link="/transition/" routeProps={{
onEffectClick: props.onEffectClick,
onEffectTypeClick: props.onEffectTypeClick,
changeDuration: props.changeDuration,
onStartClick: props.onStartClick,
onDelayCheck: props.onDelayCheck,
onDelay: props.onDelay,
onApplyAll: props.onApplyAll
}}></ListItem>
<ListItem title={_t.textStyle} link="/style/" routeProps={{
onFillColor: props.onFillColor
}}></ListItem>
</List>
<List className="buttons-list">
<ListButton className="button-fill button-raised" onClick={props.onDuplicateSlide}>{_t.textDuplicateSlide}</ListButton>
<ListButton className="button-red button-fill button-raised" onClick={props.onRemoveSlide}>{_t.textDeleteSlide}</ListButton>
</List>
</Fragment>
)
};
const PageTheme = props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const storeSlideSettings = props.storeSlideSettings;
const arrayThemes = storeSlideSettings.arrayThemes;
const slideThemeIndex = storeSlideSettings.slideThemeIndex;
return (
<Page className="slide-theme">
<Navbar title={_t.textTheme} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
{arrayThemes.length && (
<List className="slide-theme__list">
{arrayThemes.map(theme => {
return (
<ListItem key={theme.themeId} className={theme.themeId === slideThemeIndex ? "item-theme active" : "item-theme"}
style={{backgroundPosition: `0 -${theme.offsety}px`, backgroundImage: theme.imageUrl && `url(${theme.imageUrl})`}}
onClick={() => {
storeSlideSettings.changeSlideThemeIndex(theme.themeId);
props.onThemeClick(theme.themeId);
}}>
</ListItem>
);
})}
</List>
)}
</Page>
);
};
const PageLayout = props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const storeFocusObjects = props.storeFocusObjects;
const storeSlideSettings = props.storeSlideSettings;
storeSlideSettings.changeSlideLayoutIndex(storeFocusObjects.slideObject.get_LayoutIndex());
const arrayLayouts = storeSlideSettings.slideLayouts;
const slideLayoutIndex = storeSlideSettings.slideLayoutIndex;
return (
<Page className="slide-layout">
<Navbar title={_t.textLayout} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
{arrayLayouts.length &&
arrayLayouts.map((layouts, index) => {
return (
<List className="slide-layout__list" key={index}>
{layouts.map(layout => {
return (
<ListItem key={layout.type} className={slideLayoutIndex === layout.type ? "active" : ""}
onClick={() => {
storeSlideSettings.changeSlideLayoutIndex(layout.type);
props.onLayoutClick(layout.type);
}}>
<img src={layout.image} style={{width: layout.width, height: layout.height}} alt=""/>
</ListItem>
)
})}
</List>
);
})
}
</Page>
);
};
const PageTransition = props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const isAndroid = Device.android;
const _arrEffect = [
{displayValue: _t.textNone, value: Asc.c_oAscSlideTransitionTypes.None},
{displayValue: _t.textFade, value: Asc.c_oAscSlideTransitionTypes.Fade},
{displayValue: _t.textPush, value: Asc.c_oAscSlideTransitionTypes.Push},
{displayValue: _t.textWipe, value: Asc.c_oAscSlideTransitionTypes.Wipe},
{displayValue: _t.textSplit, value: Asc.c_oAscSlideTransitionTypes.Split},
{displayValue: _t.textUnCover, value: Asc.c_oAscSlideTransitionTypes.UnCover},
{displayValue: _t.textCover, value: Asc.c_oAscSlideTransitionTypes.Cover},
{displayValue: _t.textClock, value: Asc.c_oAscSlideTransitionTypes.Clock},
{displayValue: _t.textZoom, value: Asc.c_oAscSlideTransitionTypes.Zoom}
];
const _arrEffectType = [
{displayValue: _t.textSmoothly, value: Asc.c_oAscSlideTransitionParams.Fade_Smoothly},
{displayValue: _t.textBlack, value: Asc.c_oAscSlideTransitionParams.Fade_Through_Black},
{displayValue: _t.textLeft, value: Asc.c_oAscSlideTransitionParams.Param_Left},
{displayValue: _t.textTop, value: Asc.c_oAscSlideTransitionParams.Param_Top},
{displayValue: _t.textRight, value: Asc.c_oAscSlideTransitionParams.Param_Right},
{displayValue: _t.textBottom, value: Asc.c_oAscSlideTransitionParams.Param_Bottom},
{displayValue: _t.textTopLeft, value: Asc.c_oAscSlideTransitionParams.Param_TopLeft},
{displayValue: _t.textTopRight, value: Asc.c_oAscSlideTransitionParams.Param_TopRight},
{displayValue: _t.textBottomLeft, value: Asc.c_oAscSlideTransitionParams.Param_BottomLeft},
{displayValue: _t.textBottomRight, value: Asc.c_oAscSlideTransitionParams.Param_BottomRight},
{displayValue: _t.textVerticalIn, value: Asc.c_oAscSlideTransitionParams.Split_VerticalIn},
{displayValue: _t.textVerticalOut, value: Asc.c_oAscSlideTransitionParams.Split_VerticalOut},
{displayValue: _t.textHorizontalIn, value: Asc.c_oAscSlideTransitionParams.Split_HorizontalIn},
{displayValue: _t.textHorizontalOut, value: Asc.c_oAscSlideTransitionParams.Split_HorizontalOut},
{displayValue: _t.textClockwise, value: Asc.c_oAscSlideTransitionParams.Clock_Clockwise},
{displayValue: _t.textCounterclockwise, value: Asc.c_oAscSlideTransitionParams.Clock_Counterclockwise},
{displayValue: _t.textWedge, value: Asc.c_oAscSlideTransitionParams.Clock_Wedge},
{displayValue: _t.textZoomIn, value: Asc.c_oAscSlideTransitionParams.Zoom_In},
{displayValue: _t.textZoomOut, value: Asc.c_oAscSlideTransitionParams.Zoom_Out},
{displayValue: _t.textZoomRotate, value: Asc.c_oAscSlideTransitionParams.Zoom_AndRotate}
];
let _arrCurrentEffectTypes = [];
const fillEffectTypes = type => {
_arrCurrentEffectTypes = [];
switch (type) {
case Asc.c_oAscSlideTransitionTypes.Fade:
_arrCurrentEffectTypes.push(_arrEffectType[0], _arrEffectType[1]);
break;
case Asc.c_oAscSlideTransitionTypes.Push:
_arrCurrentEffectTypes = _arrEffectType.slice(2, 6);
break;
case Asc.c_oAscSlideTransitionTypes.Wipe:
_arrCurrentEffectTypes = _arrEffectType.slice(2, 10);
break;
case Asc.c_oAscSlideTransitionTypes.Split:
_arrCurrentEffectTypes = _arrEffectType.slice(10, 14);
break;
case Asc.c_oAscSlideTransitionTypes.UnCover:
_arrCurrentEffectTypes = _arrEffectType.slice(2, 10);
break;
case Asc.c_oAscSlideTransitionTypes.Cover:
_arrCurrentEffectTypes = _arrEffectType.slice(2, 10);
break;
case Asc.c_oAscSlideTransitionTypes.Clock:
_arrCurrentEffectTypes = _arrEffectType.slice(14, 17);
break;
case Asc.c_oAscSlideTransitionTypes.Zoom:
_arrCurrentEffectTypes = _arrEffectType.slice(17);
break;
}
return (_arrCurrentEffectTypes.length > 0) ? _arrCurrentEffectTypes[0].value : -1;
};
const getEffectName = effect => {
for (var i=0; i < _arrEffect.length; i++) {
if (_arrEffect[i].value == effect) return _arrEffect[i].displayValue;
}
return '';
};
const getEffectTypeName = type => {
for (var i=0; i < _arrCurrentEffectTypes.length; i++) {
if (_arrCurrentEffectTypes[i].value == type) return _arrCurrentEffectTypes[i].displayValue;
}
return '';
};
const storeFocusObjects = props.storeFocusObjects;
const transitionObj = storeFocusObjects.slideObject.get_transition();
let _effectDelay = transitionObj.get_SlideAdvanceDuration();
const [stateRange, changeRange] = useState((_effectDelay !== null && _effectDelay !== undefined) ? parseInt(_effectDelay / 1000.) : 0);
const isDelay = transitionObj.get_SlideAdvanceAfter();
const isStartOnClick = transitionObj.get_SlideAdvanceOnMouseClick();
const _effect = transitionObj.get_TransitionType();
const nameEffect = getEffectName(_effect);
if(_effect != Asc.c_oAscSlideTransitionTypes.None) fillEffectTypes(_effect);
const _effectType = transitionObj.get_TransitionOption();
const nameEffectType = getEffectTypeName(_effectType);
const _effectDuration = transitionObj.get_TransitionDuration();
useEffect(() => {
changeRange((_effectDelay !== null && _effectDelay !== undefined) ? parseInt(_effectDelay / 1000.) : 0);
}, [_effectDelay])
return (
<Page className="slide-transition">
<Navbar title={t('View.Edit.textTransitions')} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<List>
<ListItem link="/effect/" title={_t.textEffect} after={nameEffect} routeProps={{
_arrEffect,
onEffectClick: props.onEffectClick,
fillEffectTypes,
_effect,
}}></ListItem>
<ListItem link="/type/" title={_t.textType}
after={_effect != Asc.c_oAscSlideTransitionTypes.None ? nameEffectType : ''}
disabled={_effect == Asc.c_oAscSlideTransitionTypes.None} routeProps={{
_arrCurrentEffectTypes,
onEffectTypeClick: props.onEffectTypeClick,
_effect,
_effectType,
}}>
</ListItem>
<ListItem title={_t.textDuration} disabled={_effect == Asc.c_oAscSlideTransitionTypes.None}>
{!isAndroid && <div slot='after-start'>
<label>{(_effectDuration !== null && _effectDuration !== undefined) ? (parseInt(_effectDuration / 1000.) + ' ' + _t.textSec) : ''}</label>
</div>}
<div slot="after" className="splitter">
<Segmented>
<Button outline className='decrement item-link' onClick={() => {
let duration = parseInt(_effectDuration / 1000);
duration = Math.max(0, --duration);
props.changeDuration(duration);
}}>
{isAndroid ? <Icon icon="icon-expand-down"></Icon> : ' - '}
</Button>
{isAndroid && <label>{(_effectDuration !== null && _effectDuration !== undefined) ? (parseInt(_effectDuration / 1000.) + ' ' + _t.textSec) : ''}</label>}
<Button outline className='increment item-link' onClick={() => {
let duration = parseInt(_effectDuration / 1000);
duration = Math.min(300, ++duration);
props.changeDuration(duration);
}}>
{isAndroid ? <Icon icon="icon-expand-up"></Icon> : ' + '}
</Button>
</Segmented>
</div>
</ListItem>
</List>
<List>
<ListItem>
<span>{_t.textStartOnClick}</span>
<Toggle checked={isStartOnClick} onToggleChange={() => {props.onStartClick(!isStartOnClick)}} />
</ListItem>
<ListItem>
<span>{_t.textDelay}</span>
<Toggle checked={isDelay} onToggleChange={() => {props.onDelayCheck(!isDelay, _effectDelay)}} />
</ListItem>
<ListItem>
<div slot='inner' style={{width: '100%'}}>
<Range min={0} max={300} step={1}
value={stateRange}
disabled={!isDelay}
onRangeChange={(value) => {changeRange(value)}}
onRangeChanged={(value) => {props.onDelay(value)}}
></Range>
</div>
<div slot='inner-end' style={{minWidth: '75px', textAlign: 'right'}}>
{stateRange + ' ' + _t.textSec}
</div>
</ListItem>
</List>
<List className="buttons-list">
<ListButton className="button-fill button-raised" onClick={props.onApplyAll}>{_t.textApplyAll}</ListButton>
</List>
</Page>
);
};
const PageEffect = props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const [currentEffect, setEffect] = useState(props._effect);
const _arrEffect = props._arrEffect;
return (
<Page className="style-effect">
<Navbar title={_t.textEffect} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
{_arrEffect.length ? (
<List mediaList>
{_arrEffect.map((elem, index) => {
return (
<ListItem key={index} radio name="editslide-effect" title={elem.displayValue} value={elem.value}
checked={elem.value === currentEffect} onChange={() => {
setEffect(elem.value);
let valueEffectTypes = props.fillEffectTypes(elem.value);
props.onEffectClick(elem.value, valueEffectTypes);
}}></ListItem>
)
})}
</List>
) : null}
</Page>
);
};
const PageType= props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const _arrCurrentEffectTypes = props._arrCurrentEffectTypes;
const [currentType, setType] = useState(props._effectType);
return (
<Page className="style-type">
<Navbar title={_t.textType} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
{_arrCurrentEffectTypes.length ? (
<List mediaList>
{_arrCurrentEffectTypes.map((elem, index) => {
return (
<ListItem key={index} radio name="editslide-effect-type" title={elem.displayValue} value={elem.value}
checked={elem.value === currentType} onChange={() => {
setType(elem.value);
props.onEffectTypeClick(elem.value, props._effect);
}}>
</ListItem>
)
})}
</List>
) : null}
</Page>
);
};
const PageFillColor = props => {
const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true });
const storeFocusObjects = props.storeFocusObjects;
const slideObject = storeFocusObjects.slideObject;
const storePalette = props.storePalette;
const storeSlideSettings = props.storeSlideSettings;
const customColors = storePalette.customColors;
const fillColor = storeSlideSettings.getFillColor(slideObject);
const changeColor = (color, effectId, effectValue) => {
if (color !== 'empty') {
if (effectId !== undefined ) {
const newColor = {color: color, effectId: effectId, effectValue: effectValue};
props.onFillColor(newColor);
storeSlideSettings.changeFillColor(newColor);
} else {
props.onFillColor(color);
storeSlideSettings.changeFillColor(color);
}
} else {
// open custom color menu
props.f7router.navigate('/edit-custom-color/', {props: {onFillColor: props.onFillColor}});
}
};
return (
<Page>
<Navbar title={_t.textFill} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<ThemeColorPalette changeColor={changeColor} curColor={fillColor} customColors={customColors} transparent={true} />
<List>
<ListItem title={_t.textAddCustomColor} link={'/edit-custom-color/'} routeProps={{
onFillColor: props.onFillColor
}}></ListItem>
</List>
</Page>
);
};
const PageCustomFillColor = props => {
const { t } = useTranslation();
const _t = t('View.Edit', {returnObjects: true});
let fillColor = props.storeSlideSettings.fillColor;
if (typeof fillColor === 'object') {
fillColor = fillColor.color;
}
const onAddNewColor = (colors, color) => {
props.storePalette.changeCustomColors(colors);
props.onFillColor(color);
props.storeSlideSettings.changeFillColor(color);
props.f7router.back();
};
return (
<Page>
<Navbar title={_t.textCustomColor} backLink={_t.textBack}>
{Device.phone &&
<NavRight>
<Link sheetClose='#edit-sheet'>
<Icon icon='icon-expand-down'/>
</Link>
</NavRight>
}
</Navbar>
<CustomColorPicker currentColor={fillColor} onAddNewColor={onAddNewColor} />
</Page>
)
};
const Theme = inject("storeSlideSettings")(observer(PageTheme));
const Layout = inject("storeSlideSettings", "storeFocusObjects")(observer(PageLayout));
const Transition = inject("storeSlideSettings", "storeFocusObjects")(observer(PageTransition));
const Type = inject("storeSlideSettings", "storeFocusObjects")(observer(PageType));
const Effect = inject("storeSlideSettings", "storeFocusObjects")(observer(PageEffect));
const StyleFillColor = inject("storeSlideSettings", "storePalette", "storeFocusObjects")(observer(PageFillColor));
const CustomFillColor = inject("storeSlideSettings", "storePalette", "storeFocusObjects")(observer(PageCustomFillColor));
export {
EditSlide,
Theme,
Layout,
Transition,
Type,
Effect,
StyleFillColor,
CustomFillColor
};