Skip to content

Commit 294052e

Browse files
committed
curve-editor: add state restore
1 parent c565a36 commit 294052e

11 files changed

+500
-155
lines changed

app/build/mojs-curve-editor.js

Lines changed: 346 additions & 130 deletions
Large diffs are not rendered by default.

app/build/mojs-curve-editor.min.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/css/blocks/point-controls.postcss.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,30 @@
77
&.is-show {
88
display: block;
99
}
10+
11+
[data-component="icon-button"] {
12+
$width: 3;
13+
$height: 2.5*$width;
14+
15+
&:after {
16+
content: '';
17+
position: absolute;
18+
width: calc( $width*$PX );
19+
height: calc( $height*$PX );
20+
background: $c-orange;
21+
border-top-right-radius: calc( 2*$PX );
22+
border-bottom-right-radius: calc( 2*$PX );
23+
/*border-radius: 50%;*/
24+
left: calc( -(3*$width + 1)*$PX );
25+
top: 50%;
26+
margin-top: calc( -($height/2)*$PX );
27+
display: none;
28+
}
29+
30+
&[class*="is-checked"] {
31+
&:after {
32+
display: block;
33+
}
34+
}
35+
}
1036
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"point-controls":"_point-controls_1j5f4_4","is-show":"_is-show_1j5f4_7"}
1+
{"point-controls":"_point-controls_1xcu7_4","is-show":"_is-show_1xcu7_7"}

app/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,9 @@
1111
<script src="/node_modules/mo-js/build/mo.js" charset="utf-8"></script>
1212
<script src="build/mojs-curve-editor.js" charset="utf-8"></script>
1313

14+
<script>
15+
new window.MojsCurveEditor;
16+
</script>
17+
1418
</body>
1519
</html>

app/js/app.babel.jsx

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,100 @@ require('../css/main');
33
import { Provider } from 'preact-redux';
44
import {render, h} from 'preact';
55
import CurveEditor from './tags/curve-editor';
6-
import store from './store';
6+
import initStore from './store';
77
import C from './constants';
8+
import hash from './helpers/hash';
9+
import fallbackTo from './helpers/fallback-to';
810

911
// TODO
10-
// - instance dropdown on code panel
11-
// - add orange point on seleced point control/ hightlight the control
12-
// - save state to LC
1312
// - add APIs
13+
// - resize down when points are above the editor border
14+
// - instance dropdown on code panel
1415
// - import path data
1516
// - move bunch of points at once
1617

17-
document.addEventListener('DOMContentLoaded', () => {
18-
render(
19-
<Provider store={store}>
20-
<CurveEditor />
21-
</Provider>, document.body);
22-
});
18+
class API {
19+
constructor ( o = {} ) {
20+
this._o = o;
21+
22+
this._decalareDefaults();
23+
this._vars();
24+
this._render();
25+
this._tryToRestore();
26+
this._listenUnload();
27+
28+
this._subscribe()
29+
}
30+
31+
_decalareDefaults ( ) {
32+
this._defaults = {
33+
name: 'mojs-curve-editor',
34+
isSaveState: true,
35+
}
36+
}
37+
38+
_vars () {
39+
this.revision = '1.0.0';
40+
this.store = initStore();
41+
42+
let str = fallbackTo( this._o.name, this._defaults.name );
43+
str += ( str === this._defaults.name ) ? '' : `__${this._defaults.name}`;
44+
this._localStorage = `${str}__${ hash( str ) }`;
45+
}
46+
47+
_render () {
48+
document.addEventListener('DOMContentLoaded', () => {
49+
render(
50+
<Provider store={this.store}>
51+
<CurveEditor />
52+
</Provider>, document.body);
53+
});
54+
}
55+
56+
_listenUnload () {
57+
const unloadEvent = ('onpagehide' in window) ? 'pagehide' : 'beforeunload';
58+
window.addEventListener( unloadEvent, () => {
59+
60+
const preState = { ...this.store.getState() };
61+
62+
delete preState.points.history;
63+
delete preState.pointControls.history;
64+
65+
localStorage.setItem(this._localStorage, JSON.stringify( preState ) );
66+
});
67+
}
68+
69+
_tryToRestore () {
70+
// localStorage.removeItem(this._localStorage);
71+
const stored = localStorage.getItem(this._localStorage);
72+
if ( stored ) { this.store.dispatch({ type: 'SET_STATE', data: JSON.parse(stored) });}
73+
else {
74+
this.store.dispatch({ type: 'POINT_ADD', data: { point: {x: 0, y: C.CURVE_SIZE, isLockedX: true}, index: 0 } });
75+
this.store.dispatch({ type: 'POINT_ADD', data: { point: {x: 100, y: 0, isLockedX: true}, index: 1 } });
76+
this.store.dispatch({ type: 'POINT_SELECT', data: { index: 0, type: 'straight' } });
77+
}
78+
}
79+
80+
_subscribe () {
81+
this._compilePath();
82+
this.store.subscribe( this._compilePath.bind(this) );
83+
}
84+
85+
_compilePath () {
86+
const state = this.store.getState(),
87+
points = state.points.present,
88+
{path} = points;
89+
90+
if ( this._prevPath !== path ) {
91+
this._prevPath = path;
92+
this._easing = mojs.easing.path( path );
93+
}
94+
}
2395

24-
store.dispatch({ type: 'POINT_ADD', data: { point: {x: 0, y: C.CURVE_SIZE, isLockedX: true}, index: 0 } });
25-
store.dispatch({ type: 'POINT_ADD', data: { point: {x: 100, y: 0, isLockedX: true}, index: 1 } });
96+
}
2697

27-
// makePoint({ x: 0, y: C.CURVE_SIZE, isLockedX: true, type: 'straight' }),
28-
// // makePoint({ x: 50, y: C.CURVE_SIZE/2, type: 'mirrored' }),
29-
// makePoint({ x: 100, y: 0, isLockedX: true })
98+
export default API;
99+
window.MojsCurveEditor = API;
30100

31101
// curve
32102
// .getFunction({ isInverseX: false, isInverseY: true, name: 'Some name' })

app/js/helpers/fallback-to.babel.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
Function that returns the second argument if the first one isn't set.
3+
@private
4+
@param {Any} Property to set.
5+
@param {Any} Property to return as fallback.
6+
@returns {Any} If set - the first property, if not - the second.
7+
*/
8+
export default (prop, fallback) => {
9+
return ( prop != null ) ? prop : fallback;
10+
}

app/js/helpers/hash.babel.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
Function to generate hash code.
3+
@private
4+
@return {String} Hash code.
5+
*/
6+
7+
export default (str) => {
8+
var hash = 0, i, chr, len;
9+
if (str.length === 0) return hash;
10+
for (i = 0, len = str.length; i < len; i++) {
11+
chr = str.charCodeAt(i);
12+
hash = ((hash << 5) - hash) + chr;
13+
hash |= 0; // Convert to 32bit integer
14+
}
15+
return Math.abs( hash );
16+
}

app/js/reducers/index-reducer.babel.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ const UNDOABLE_OPTS = {
1616
debug: false
1717
};
1818

19-
const reducer = combineReducers({
19+
import recycleState from 'redux-recycle'
20+
21+
const reducer = recycleState(combineReducers({
2022
resize: resizeReducer,
2123
points: undoable(pointsReducer, { ...UNDOABLE_OPTS }),
2224
controls: controlsReducer,
2325
pointControls: undoable(pointControlsReducer, { ...UNDOABLE_OPTS })
24-
});
26+
}), ['SET_STATE'], (state, action) => action.data );
2527

2628
export default reducer;

app/js/store.babel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import {createStore} from 'redux';
22
// import reducer
33
import reducer from './reducers/index-reducer';
44

5-
const store = createStore( reducer );
5+
const initStore = () => { return createStore( reducer ); }
66

7-
export default store;
7+
export default initStore;

0 commit comments

Comments
 (0)