Skip to content
New issue

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

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

Already on GitHub? # to your account

React update #37

Merged
merged 2 commits into from
Nov 7, 2018
Merged
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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -3,5 +3,4 @@ node_modules
npm-debug.log
build/*.js
build/*.js.map
package-lock.json
mercurywm-*.zip
5,765 changes: 5,765 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "mercurywm",
"version": "1.1.0",
"version": "2.0.0",
"description": "New tab page with multi-windowed terminals",
"main": "src/index.js",
"scripts": {
"dev": "webpack --progress --watch",
"prod": "cross-env NODE_ENV=production webpack -p --progress",
"test": "flow check",
"travis": "npm run prod && zip -r mercurywm-$(date +%s).zip build/"
},
"repository": {
@@ -24,8 +25,8 @@
"flow-bin": "^0.85.0",
"flow-interfaces-chrome": "^0.4.0",
"flow-typed": "^2.5.1",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"remove-flow-types-loader": "^1.1.0",
2 changes: 1 addition & 1 deletion src/mercury/components/loading.jsx
Original file line number Diff line number Diff line change
@@ -19,4 +19,4 @@ const Loading = () => (
</div>
);

module.exports = Loading;
export default Loading;
2 changes: 1 addition & 1 deletion src/mercury/components/root.jsx
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ type DispatchProps = {|
type Props = StateProps & DispatchProps;

class Root extends React.Component<Props> {
componentWillMount() {
componentDidMount() {
window.addEventListener('keydown', (e: KeyboardEvent) => this.handleSystemKey(e), true);
window.addEventListener('message', (e: MessageEvent) => this.receiveMessage(e), false);
}
118 changes: 118 additions & 0 deletions src/mercury/components/scroll.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* @flow strict */

import * as React from 'react';

type Props = {|
+children: React.Node,
+selected: boolean,
+handleKey: (e: SyntheticKeyboardEvent<HTMLDivElement>) => void,
+onPaste: (data: string) => void
|};

class SmoothScroll extends React.Component<Props> {
animation: ?AnimationFrameID;
input = React.createRef();

componentDidMount() {
const box = this.input.current;
if (!box) return;

if (this.props.selected) {
box.focus();
}

box.scrollTop = box.scrollHeight;

box.addEventListener('paste', (event: ClipboardEvent) => {
const clipboardData = event.clipboardData;
if (!clipboardData) return;

const data = clipboardData.getData('text/plain');
this.props.onPaste(data);
});
}

componentDidUpdate() {
if (this.props.selected) {
const box = this.input.current;
if (box) box.focus();

this.startSmoothScroll(100, x => 3 * x * x - 2 * x * x * x);
}
}

handleKey = (e: SyntheticKeyboardEvent<HTMLDivElement>) => {
if (!this.props.selected) return;

if (this.input && this.input.current) {
this.input.current.scrollTop = this.input.current.scrollHeight;
}

this.props.handleKey(e);
};

startSmoothScroll(duration: number, interpolator: number => number) {
// Cancel any ongoing scrolling
if (this.animation) {
cancelAnimationFrame(this.animation);
this.animation = null;
}

const box = this.input.current;
if (!box) {
return;
}

// Start and end points
const animationStart = box.scrollTop;
const animationEnd = box.scrollHeight - box.offsetHeight;

// Finish scrolling
if (animationStart >= animationEnd) {
box.scrollTop = animationEnd;
return;
}

const startTime = performance.now();

const animate = (currTime: DOMHighResTimeStamp) => {
const deltaTime = currTime - startTime;
// Duration over, finish scrolling
if (deltaTime > duration) {
if (this.animation) {
cancelAnimationFrame(this.animation);
this.animation = null;
}
if (box) box.scrollTop = animationEnd;
return;
}

// Continue scrolling
const timeStep = deltaTime / duration;
const newTop =
animationStart +
interpolator(timeStep) * (animationEnd - animationStart);
if (box) box.scrollTop = newTop;

this.animation = requestAnimationFrame(animate);
};

// Start animating
this.animation = requestAnimationFrame(animate);
}

render(): React.Node {
return (
<div
className="terminal-link"
ref={this.input}
tabIndex="1"
onKeyDown={this.handleKey}
>
{this.props.children}
</div>
);
}
}

export default SmoothScroll;
Loading