import React from 'react'; import ls from './HistoryTimeline.less'; import connect from 'ui/connect'; import decoratorChain from 'ui/decoratorChain'; import {finishHistoryEditing, removeAndDropDependants} from '../craftHistoryUtils'; import mapContext from 'ui/mapContext'; import ImgIcon from 'ui/components/ImgIcon'; import cx from 'classnames'; import Fa from 'ui/components/Fa'; import {combine} from 'lstream'; import {EMPTY_OBJECT} from 'gems/objects'; import {aboveElement} from 'ui/positionUtils'; import {resolveAppearance} from "cad/craft/operationHelper"; import {menuAboveElementHint} from "cad/dom/menu/menuUtils"; @connect(streams => combine(streams.craft.modifications, streams.operation.registry, streams.wizard.insertOperation) .map(([modifications, operationRegistry, insertOperationReq]) => ({ ...modifications, operationRegistry, inProgressOperation: !!insertOperationReq, getOperation: type => operationRegistry[type]||EMPTY_OBJECT }))) @mapContext(({streams, services}) => ({ remove: atIndex => streams.craft.modifications.update(modifications => removeAndDropDependants(modifications, atIndex)), cancel: () => streams.craft.modifications.update(modifications => finishHistoryEditing(modifications)), setHistoryPointer: pointer => streams.craft.modifications.update(({history}) => ({history, pointer})), rebuild: () => services.craft.rebuild() })) export default class HistoryTimeline extends React.Component { render() { const {history, pointer, setHistoryPointer, rebuild, getOperation, inProgressOperation} = this.props; let scrolly; const eof = history.length-1; return
scrolly.scrollLeft -= 60}>
scrolly = el}> {history.map((m, i) => setHistoryPointer(i-1)} /> { inProgressOperation && i-1 === pointer && } )} setHistoryPointer(eof)}/> {inProgressOperation && eof === pointer && }
scrolly.scrollLeft += 60}>
; } // scrollInProgressToVisibleRequest = false; setHistoryPointerAndRequestScroll = (pointer) => { // this.scrollInProgressToVisibleRequest = true; this.props.setHistoryPointer(pointer); }; keepRef = el => this.el = el; componentDidUpdate() { // this.scrollInProgressToVisibleRequest = false; setTimeout(() => { const item = this.el.querySelector(`.${ls.history} .${ls.inProgress}`); if (item) { item.scrollIntoView({behavior: "smooth", inline: "center", block: "end"}); } else { const history = this.el.querySelector(`.${ls.history}`); history.scrollLeft = history.scrollWidth; } }) } } function FutureItem({appearance}) { return
; } function Timesplitter({active, eoh, onClick}) { return
; } function Handle() { const w = 12; const h = 15; const m = Math.round(w * 0.5); const t = Math.round(h * 0.5); return ; } function Controls({rebuild, history, pointer, eoh, setHistoryPointer, }) { const noB = pointer===-1; const noF = pointer===eoh; return
setHistoryPointer(pointer-1)}>
setHistoryPointer(pointer+1)}>
setHistoryPointer(eoh)}>
; } const HistoryItem = decoratorChain( connect((streams, props) => streams.ui.craft.modificationSelection.map(s => ({ selected: s.index === props.index, }))), mapContext(({streams}) => ({ toggle: (index, modification, el) => streams.ui.craft.modificationSelection.update(s => s.index === index ? EMPTY_OBJECT : {index, locationHint: aboveElement(el)}) })) ) ( // eslint-disable-line no-unexpected-multiline function HistoryItem({index, pointer, modification, getOperation, toggle, selected, disabled, inProgress}) { const operation = getOperation(modification.type); const appearance = resolveAppearance(operation, modification.params); return
toggle(index, modification, e.currentTarget)}> { modification.params.featureId }
; }); const AddButton = mapContext((ctx) => ({ showCraftMenu: e => ctx.actionService.run('menu.craft', menuAboveElementHint(e.currentTarget)) }))( function AddButton({showCraftMenu}) { return
; } );