improve history timeline scroll

This commit is contained in:
Val Erastov 2018-07-06 17:01:58 -07:00
parent b8053c5e25
commit 6f95b5ae80
8 changed files with 160 additions and 36 deletions

View file

@ -14,19 +14,52 @@ import {EMPTY_OBJECT} from '../../../../../modules/gems/objects';
import {VIEWER_SELECTOR} from '../../dom/components/View3d';
import {aboveElement} from '../../../../../modules/ui/positionUtils';
function HistoryTimeline({history, pointer, setHistoryPointer, remove, getOperation}) {
return <div className={ls.root}>
<Controls pointer={pointer} eoh={history.length-1} setHistoryPointer={setHistoryPointer}/>
{history.map((m, i) => <React.Fragment key={i}>
<Timesplitter active={i-1 === pointer} onClick={() => setHistoryPointer(i-1)} />
<HistoryItem index={i} modification={m} getOperation={getOperation}
disabled={pointer < i}
inProgress={pointer === i-1} />
</React.Fragment>)}
<Timesplitter eoh active={history.length-1 === pointer} onClick={() => setHistoryPointer(history.length-1)}/>
<InProgressOperation getOperation={getOperation}/>
<AddButton />
</div>;
class HistoryTimeline extends React.Component {
render() {
let {history, pointer, setHistoryPointer, remove, getOperation} = this.props;
let scrolly;
return <div className={ls.root} ref={this.keepRef}>
<Controls pointer={pointer} eoh={history.length-1} setHistoryPointer={this.setHistoryPointerAndRequestScroll}/>
<div className={ls.scroller} onClick={e => scrolly.scrollLeft -= 60}><Fa icon='caret-left'/></div>
<div className={ls.history} ref={el => scrolly = el}>
{history.map((m, i) => <React.Fragment key={i}>
<Timesplitter active={i-1 === pointer} onClick={() => setHistoryPointer(i-1)} />
<HistoryItem index={i} modification={m} getOperation={getOperation}
disabled={pointer < i}
inProgress={pointer === i-1} />
</React.Fragment>)}
<Timesplitter eoh active={history.length-1 === pointer} onClick={() => setHistoryPointer(history.length-1)}/>
</div>
<div className={ls.scroller} onClick={e => scrolly.scrollLeft += 60}><Fa icon='caret-right'/></div>
<InProgressOperation getOperation={getOperation}/>
<AddButton />
</div>;
}
// scrollInProgressToVisibleRequest = false;
setHistoryPointerAndRequestScroll = (pointer) => {
// this.scrollInProgressToVisibleRequest = true;
this.props.setHistoryPointer(pointer);
};
keepRef = el => this.el = el;
componentDidUpdate() {
// this.scrollInProgressToVisibleRequest = false;
setTimeout(() => {
let item = this.el.querySelector(`.${ls.historyItem}.${ls.inProgress}`);
if (item) {
item.scrollIntoView({behavior: "smooth", inline: "center"});
} else {
let history = this.el.querySelector(`.${ls.history}`);
history.scrollLeft = history.scrollWidth;
}
})
}
}
const InProgressOperation = connect(streams => streams.wizard.map(wizard => ({wizard})))(

View file

@ -3,8 +3,9 @@
.root {
background-color: rgba(0, 0, 0, 0.1);
display: flex;
align-items: stretch;
height: 34px;
align-items: flex-end;
height: 48px;
//&:hover .timesplitter .handlePoly {
// visibility: visible;
//}
@ -14,13 +15,37 @@
width: 4px;
height: 100%;
cursor: pointer;
align-items: flex-end;
.handle {
margin-top: -15px;
//margin-top: -15px;
margin-left: -4px;
font-size: 20px;
}
}
.history {
display: flex;
align-items: flex-end;
height: 100%;
overflow-x: hidden;
padding: 0 5px;
}
.scroller {
padding: 0 5px;
height: 100%;
display: flex;
align-items: center;
cursor: pointer;
&:hover {
background-color: #BFBFBF;
}
&:active {
background-color: #7e7e7e;
transition: 100ms;
}
}
.timesplitter.active:not(.eoh) {
background-color: #ff940b;
@ -50,6 +75,8 @@
//ITEMS
.item {
height: 30px;
flex-shrink: 0;
margin: 2px 0;
padding: 2px;
border: #2e2e2e 1px solid;

View file

@ -6,8 +6,7 @@
background-color: #780000;
}
display: flex;
justify-content: space-between;
align-items: baseline;
align-items: center;
& .buttons {
display: none;
}
@ -19,6 +18,7 @@
.buttons {
display: none;
font-size: 13px;
margin-left: auto;
& > * {
padding: 0 3px;
&.danger:hover {

View file

@ -5,7 +5,6 @@ import decoratorChain from '../../../../../modules/ui/decoratorChain';
import {combine, merger} from '../../../../../modules/lstream';
import ls from './SelectedModificationInfo.less';
import ImgIcon from 'ui/components/ImgIcon';
import YAML from 'yamljs';
import mapContext from 'ui/mapContext';
import {EMPTY_OBJECT} from '../../../../../modules/gems/objects';
import ButtonGroup from '../../../../../modules/ui/components/controls/ButtonGroup';

View file

@ -1,16 +1,45 @@
import React, {Fragment} from 'react';
import React from 'react';
import ObjectExplorer from '../../craft/ui/ObjectExplorer';
import OperationHistory from '../../craft/ui/OperationHistory';
import Folder from 'ui/components/Folder';
import Fa from '../../../../../modules/ui/components/Fa';
import ls from './FloatView.less';
import cx from 'classnames';
export default function FloatView() {
return <Fragment>
<Folder title={<span> <Fa fw icon='cubes' /> Model</span>}>
<ObjectExplorer/>
</Folder>
<Folder title={<span> <Fa fw icon='history' /> Modifications</span>}>
<OperationHistory/>
</Folder>
</Fragment>;
export default class FloatView extends React.Component {
state = {
selected: null
};
render() {
return <div className={ls.root}>
<div className={ls.tabs}>
{['project', 'history'].map(tabId => <Tab selected={this.state.selected === tabId} key={tabId}
onClick={() => this.setState({selected: this.state.selected === tabId ? null : tabId})}>{getIcon(tabId)}</Tab>)}
</div>
{this.state.selected && <div className={ls.main}>
{this.state.selected === 'project' && <Folder title={<span> <Fa fw icon='cubes'/> Model</span>}>
<ObjectExplorer/>
</Folder>}
{this.state.selected === 'history' && <Folder title={<span> <Fa fw icon='history'/> Modifications</span>}>
<OperationHistory/>
</Folder>}
</div>}
</div>;
}
}
function Tab({children, selected, onClick}) {
return <div className={cx(ls.tab, selected && ls.selected)} onClick={onClick}>{children}</div>;
}
function getIcon(id) {
if (id === 'history') {
return <Fa fw icon='history'/>;
} else if (id === 'project') {
return <Fa fw icon='file-o'/>;
}
}

View file

@ -0,0 +1,42 @@
@import "~ui/styles/theme.less";
.root {
display: flex;
}
.tabs {
position: relative;
border-right: 1px solid @border-color;
background-color: @bg-color-alt;
font-size: 13px;
}
.main {
display: flex;
flex-direction: column;
width: 235px;
flex: 1;
overflow-y: scroll;
}
.tab {
border: 1px solid @bg-color;
margin: 3px;
border-radius: 3px;
padding: 5px 2px;
cursor: pointer;
background-color: @bg-color;
&:hover {
background-color: #9c9c9c !important;
}
&:active {
transition: 200ms;
background-color: #BFBFBF !important;
}
&.selected {
background-color: #7d7d7d;
}
}

View file

@ -20,9 +20,7 @@ export default class View3d extends React.Component {
render() {
return <UISystem className={ls.root}>
<div className={ls.sideBar}>
<FloatView />
</div>
<FloatView />
<div className={ls.viewer} id='viewer-container'>
<Abs left='0.8em' top='0.8em'>
<HeadsUpToolbar/>

View file

@ -10,7 +10,3 @@
position: relative;
overflow: hidden;
}
.sideBar {
flex-basis: 250px;
}