Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] New interface #24

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
presets: ["es2015"],
plugins: ["transform-object-rest-spread"]
}
31 changes: 8 additions & 23 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const {Rx, run} = require('@cycle/core');
const {run} = require('@cycle/core');
const {h, makeDOMDriver} = require('@cycle/dom');
const logStreams = require('../src/time-travel');
const {Observable} = require('rx');
const TimeTravel = require('../src/time-travel');

require('babel/register');

Expand All @@ -17,15 +18,14 @@ function view (count$) {
}

function model ({increment$, decrement$}) {
const action$ = Rx.Observable.merge(
const countChange$ = Observable.merge(
increment$.map(_ => +1),
decrement$.map(_ => -1)
);

const count$ = action$.scan((count, value) => count + value)
return countChange$
.scan((count, change) => count + change)
.startWith(0);

return {count$, action$};
}

function intent (DOM) {
Expand All @@ -36,28 +36,13 @@ function intent (DOM) {
}

function main ({DOM}) {
const userIntent = intent(DOM);
const {count$, action$} = model(userIntent);

const logStream = logStreams(DOM, [
{stream: count$, label: 'count$'},
{stream: action$, label: 'action$'}
]);

const app = view(logStream.timeTravel.count$);

return {
DOM: Rx.Observable.combineLatest(app, logStream.DOM)
.map(vtrees => (
h('.app', vtrees)
)
)
DOM: view(model(intent(DOM)))
};
}

const drivers = {
DOM: makeDOMDriver('.cycle')
};

run(main, drivers);

TimeTravel.run(main, drivers);
22 changes: 14 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"scripts": {
"precompile-lib": "rm -rf lib/ && mkdir -p lib",
"compile-lib": "babel --optional es7.objectRestSpread src -d lib",
"compile-lib": "babel src -d lib",
"browserify": "browserify src/time-travel.js -t babelify --outfile dist/time-travel.js",
"test-browser": "./node_modules/mochify/bin/cmd.js --transform babelify",
"prepublish": "npm run compile-lib",
Expand All @@ -31,16 +31,22 @@
},
"homepage": "https://github.com/Widdershin/cycle-time-travel",
"dependencies": {
"@cycle/core": "3.1.0",
"@cycle/dom": "5.3.0",
"@cycle/http": "3.1.0",
"es6-shim": "0.33.3"
"@cycle/core": "^6.0.0",
"@cycle/dom": "^9.0.2",
"cycle-restart": "0.0.8",
"es6-shim": "0.33.3",
"lodash": "^4.6.1",
"rx": "^4.0.7"
},
"devDependencies": {
"babel": "5.8.23",
"babelify": "6.3.0",
"babel-cli": "^6.6.5",
"babel-core": "^6.5.2",
"babel-plugin-transform-object-rest-spread": "^6.5.0",
"babel-preset-es2015": "^6.5.0",
"babelify": "^7.2.0",
"jquery": "2.1.4",
"mocha": "2.3.3",
"mochify": "2.13.0"
"mochify": "2.13.0",
"simulant": "^0.1.5"
}
}
4 changes: 2 additions & 2 deletions src/calculate-time-travel-position.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {Rx} = require('@cycle/core');
const {Observable} = require('rx');

function calculateTimestamp (mouseX) {
return mouseX / document.documentElement.clientWidth * 10000;
Expand Down Expand Up @@ -26,7 +26,7 @@ function makeTimeTravelPosition$ (mousePosition$, dragging$) {
dragging: false
};

const currentPositionAndDragState$ = Rx.Observable.combineLatest(
const currentPositionAndDragState$ = Observable.combineLatest(
mousePosition$,
dragging$,
(mousePosition, dragging) => ({ mousePosition, dragging })
Expand Down
10 changes: 5 additions & 5 deletions src/intent.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {Rx} = require('@cycle/core');
const {Observable} = require('rx');
const makeTimeTravelPosition$ = require('./calculate-time-travel-position');

function getMousePosition (ev) {
Expand All @@ -11,12 +11,12 @@ function getMousePosition (ev) {
function intent (DOM) {
const mousePosition$ = DOM.select('.stream').events('mousemove')
.map(getMousePosition)
.startWith({x: 0, y: 0});
.startWith({x: 0, y: 0})

const click$ = DOM.select('.stream').events('mousedown');
const release$ = Rx.Observable.fromEvent(document.body, 'mouseup');
const release$ = Observable.fromEvent(document.body, 'mouseup');

const dragging$ = Rx.Observable.merge(
const dragging$ = Observable.merge(
click$.map(_ => true),
release$.map(_ => false)
).startWith(false);
Expand All @@ -25,7 +25,7 @@ function intent (DOM) {
.scan((previous, _) => !previous, true)
.startWith(true);

const playing$ = Rx.Observable.combineLatest(
const playing$ = Observable.combineLatest(
dragging$,
playingClick$,
(dragging, playingClick) => {
Expand Down
6 changes: 4 additions & 2 deletions src/record-streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ function recordStream (streamInfo, time$) {
return recordedStream;
}

function recordStreams (streams, time$) {
return streams.map(streamInfo => recordStream(streamInfo, time$));
function recordStreams (streams$, time$) {
return streams$.map(streams => {
return streams.map(streamInfo => recordStream(streamInfo, time$))
});
}

module.exports = recordStreams;
37 changes: 32 additions & 5 deletions src/render-streams.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
const {h} = require('@cycle/dom');
const _ = require('lodash');

const startDate = new Date();

function calculateValuePosition (startPercentage, currentTime, streamValue) {
const occurrenceTimeAgoInMs = currentTime - streamValue.timestamp;
const occurrenceTimeAgoInMs = currentTime + (startDate.valueOf() - streamValue.time.valueOf());

return (startPercentage - (occurrenceTimeAgoInMs / 10000) * startPercentage);
}
Expand All @@ -15,7 +18,19 @@ function renderFeatureValue (value) {
}

function renderValue (value) {
return JSON.stringify(value, null, 0);
if (typeof value === 'object' && 'subscribe' in value) {
return '$';
}

if (typeof value === 'object' && 'isTrusted' in value) {
return 'ev';
}

try {
return JSON.stringify(value, null, 0);
} catch (e) {
return 'E!' + e.message;
}
}

function renderStreamValue (currentTime, feature, streamValue) {
Expand All @@ -30,7 +45,7 @@ function renderStreamValue (currentTime, feature, streamValue) {
return (
h('pre.stream-value',
{style: {left: left + '%'}},
valueRenderer(streamValue.value)
valueRenderer(streamValue.event)
)
);
}
Expand All @@ -52,8 +67,20 @@ function renderStream (currentTime, streamValues, even) {
}

function renderStreams (currentTime, ...streamValues) {
return h('.streams', streamValues.map((streamValueSet, index) =>
renderStream(currentTime, streamValueSet, index % 2 == 0)
const streamsToRender = streamValues.map((streamValueSet) => {
const groupedStreams = _.groupBy(streamValueSet, 'identifier');

return Object.keys(groupedStreams).map(identifier => {
const stream = groupedStreams[identifier];

stream.label = identifier;

return stream;
});
});

return h('.streams', _.flatten(streamsToRender).map((streamValueSet, index) =>
renderStream(currentTime, streamValueSet, index % 2 === 0)
));
}

Expand Down
2 changes: 1 addition & 1 deletion src/time-travel-streams.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const {Rx} = require('@cycle/core');

function timeTravelStreams (streams, time$) {
function timeTravelStreams (streams$, time$) {
const timeTravel = {};

streams.forEach((recordedStream, index) => {
Expand Down
109 changes: 102 additions & 7 deletions src/time-travel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,118 @@ require('es6-shim');
const intent = require('./intent');
const makeTime$ = require('./time');
const record = require('./record-streams');
const timeTravelStreams = require('./time-travel-streams');
const timeTravelBarView = require('./view');
const scopedDOM = require('./scoped-dom');
const {restart, restartable} = require('cycle-restart');

function TimeTravel (DOM, streams, name = '.time-travel') {
const Cycle = require('@cycle/core');
const {makeDOMDriver} = require('@cycle/dom');
const {Subject} = require('rx');

function walkObservableTree (stream) {
if (stream.sources === undefined && stream.source === undefined) {
return [stream];
}

if (stream.sources) {
return [stream].concat(...stream.sources.s.map(walkObservableTree));
}

if (stream.source) {
return [stream].concat(walkObservableTree(stream.source));
}
}

function accumulatorLabel (accumulator) {
return accumulator.toString()
.replace(/"use strict";\n\n/g, '')
.split('\n')
.join('')
.replace(' ', '');
}

function run (main, drivers) {
const timeTravelBarNode = document.createElement('div');
document.body.appendChild(timeTravelBarNode);

const timeTravelDOMDriver = makeDOMDriver(timeTravelBarNode);

const streamsToDisplay$ = new Subject();

const timeTravelMain = function ({DOM}) {
const timeTravel = TimeTravel(DOM, streamsToDisplay$.startWith([]));

return {
DOM: timeTravel.DOM,
TIME: timeTravel.time$,
restart$: timeTravel.restart$
};
};

const {sources: timeSources, sinks: timeSinks} = Cycle.run(timeTravelMain, {DOM: timeTravelDOMDriver});

const restartableDrivers = {};

Object.keys(drivers).forEach(driverName => {
let args = {};

if (driverName === 'DOM') {
args = {pauseSinksWhileReplaying: false};
}

restartableDrivers[driverName] = restartable(drivers[driverName], args);
});

let {sources, sinks} = Cycle.run(main, restartableDrivers);

const startTime = new Date();

timeSinks.restart$.withLatestFrom(timeSinks.TIME).subscribe(([relative, time]) => {
console.log('honking good time', relative, new Date());
const timeToTravelTo = startTime.valueOf() + time
const blah = restart(main, restartableDrivers, {sources, sinks}, null, new Date(timeToTravelTo))
sinks = blah.sinks
sources = blah.sources

const streamsToDisplay = [sources.DOM.log$.tap(log => log.label = 'DOM')];

setTimeout(() => {
streamsToDisplay$.onNext(streamsToDisplay);
}, 1);
});

//const streamsToDisplay = walkObservableTree(sinks.DOM.source).map((stream, index) => {
// if (stream.accumulator) {
// return {stream: stream, label: accumulatorLabel(stream.accumulator)};
// }
//
// return {stream: stream, label: index.toString()};
// });

const streamsToDisplay = [sources.DOM.log$.tap(log => log.label = 'DOM')];

setTimeout(() => {
streamsToDisplay$.onNext(streamsToDisplay);
}, 1);

return {sinks, sources};
}

function TimeTravel (DOM, streams$, name = '.time-travel') {
const {timeTravelPosition$, playing$} = intent(scopedDOM(DOM, name));

const time$ = makeTime$(playing$, timeTravelPosition$);

const recordedStreams = record(streams, time$);

const timeTravel = timeTravelStreams(recordedStreams, time$);
const restart$ = timeTravelPosition$.distinctUntilChanged().sample(50).skip(1);
const recordedStreams$ = record(streams$, time$);

return {
DOM: timeTravelBarView(name, time$, playing$, recordedStreams),
timeTravel
DOM: timeTravelBarView(name, time$, playing$, streams$),
time$,
restart$
};
}

TimeTravel.run = run;

module.exports = TimeTravel;
6 changes: 3 additions & 3 deletions src/time.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const {Rx} = require('@cycle/core');
const {Observable} = require('rx');

function getCurrentTime () {
return new Date().getTime();
}

function makeTime$ (playing$, timeTravelPosition$) {
// TODO - use requestAnimationFrame scheduler
return Rx.Observable.combineLatest(
Rx.Observable.interval(16),
return Observable.combineLatest(
Observable.interval(16),
playing$,
(_, playing) => (playing)
).scan((oldTime, playing) => {
Expand Down
9 changes: 5 additions & 4 deletions src/view.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const {Rx} = require('@cycle/core');
const {Observable} = require('rx');
const {h} = require('@cycle/dom');

const renderStreams = require('./render-streams');
const stylesheet = require('./style');

function timeTravelBarView (name, time$, playing$, recordedStreams) {
return Rx.Observable.combineLatest(time$, playing$, ...recordedStreams,
(currentTime, playing, ...streamValues) => {
function timeTravelBarView (name, time$, playing$, recordedStreams$) {
console.log(recordedStreams$);
return Observable.combineLatest(time$, playing$, recordedStreams$.flatMapLatest(Observable.combineLatest),
(currentTime, playing, streamValues) => {
return h(name, [
stylesheet(),
h('button.pause', playing ? 'Pause' : 'Play'),
Expand Down
Loading