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

[icons] New iteration #12170

Merged
merged 1 commit into from
Jul 18, 2018
Merged
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
13 changes: 12 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@
]
},
"development": {
"sourceMaps": "both"
"plugins": [
[
"module-resolver",
{
"alias": {
"modules": "./modules",
}
}
]
]
},
"docs-development": {
"plugins": [
Expand All @@ -40,6 +49,7 @@
"@material-ui/icons": "./packages/material-ui-icons/src",
"@material-ui/lab": "./packages/material-ui-lab/src",
"docs": "./docs",
"modules": "./modules",
"pages": "./pages"
}
}
Expand All @@ -58,6 +68,7 @@
"@material-ui/icons": "./packages/material-ui-icons/src",
"@material-ui/lab": "./packages/material-ui-lab/src",
"docs": "./docs",
"modules": "./modules",
"pages": "./pages"
}
}
Expand Down
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/packages/material-ui-codemod/src/*/*.test
/packages/material-ui-codemod/src/*/*.test.js
/packages/material-ui-icons/src
/packages/material-ui-icons/test/fixtures
/packages/material-ui-icons/fixtures
/packages/material-ui-icons/templateSvgIcon.js
/tmp
build
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/coverage
/docs/export
/packages/material-ui-codemod/lib
/packages/material-ui-icons/material-design-icons
/packages/material-ui-icons/material-io-tools-icons
/test/regressions/screenshots
/test/selenium-output
/tmp
Expand Down
9 changes: 2 additions & 7 deletions docs/src/modules/components/Notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'isomorphic-fetch';
import React from 'react';
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import sleep from 'modules/waterfall/sleep';

function getLastSeenNotification() {
const seen = document.cookie.replace(
Expand All @@ -13,18 +14,12 @@ function getLastSeenNotification() {
return seen === '' ? 0 : parseInt(seen, 10);
}

function pause(timeout) {
return new Promise(accept => {
setTimeout(accept, timeout);
});
}

let messages = null;

async function getMessages() {
try {
if (!messages) {
await pause(1e3); // Soften the pressure on the main thread.
await sleep(1e3); // Soften the pressure on the main thread.
const result = await fetch(
'https://raw.githubusercontent.com/mui-org/material-ui/master/docs/notifications.json',
);
Expand Down
35 changes: 35 additions & 0 deletions docs/src/pages/style/icons/SvgMaterialIconsAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';

const requireIcons = require.context('../../../../../packages/material-ui-icons/src', true, /js$/);

const styles = theme => ({
root: {
color: theme.palette.text.primary,
maxHeight: 300,
overflow: 'auto',
},
});

function SvgMaterialIconsAll(props) {
const { classes } = props;
return (
<div className={classes.root}>
{requireIcons.keys().map(key => {
if (key === './index.js' || key === './utils/createSvgIcon.js') {
return null;
}

const Icon = requireIcons(key).default;
return <Icon key={key} />;
})}
</div>
);
}

SvgMaterialIconsAll.propTypes = {
classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(SvgMaterialIconsAll);
47 changes: 47 additions & 0 deletions modules/waterfall/Batcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Inspired by http://caolan.github.io/async/docs.html#cargo
// The main difference is that we have a timeout.
class Batcher {
pendingEntries = [];

timeout = null;

context = {};

constructor(worker, options = {}) {
// max waiting time before flushing the pending entries (process them)
this.maxWait = options.maxWait || 1000;
// max number of entries in the queue before flushing them (process them)
this.maxItems = options.maxItems || 100;
this.worker = worker;
}

// public method
push(entries, contextItem) {
this.context = contextItem;
this.pendingEntries = this.pendingEntries.concat(entries);

if (this.pendingEntries.length >= this.maxItems) {
return this.sendItems();
}

clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.sendItems();
}, this.maxWait);

return null;
}

sendItems() {
const pendingEntries = this.pendingEntries.splice(0); // Transfer the item to the job.
clearTimeout(this.timeout);
return this.worker(pendingEntries, this.context);
}

clear() {
clearTimeout(this.timeout);
this.pendingEntries = [];
}
}

export default Batcher;
59 changes: 59 additions & 0 deletions modules/waterfall/Queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import waitUntil from './waitUntil';

class Queue {
pendingEntries = [];

inFlight = 0;

err = null;

constructor(worker, options = {}) {
this.worker = worker;
this.concurrency = options.concurrency || 1;
}

push = entries => {
this.pendingEntries = this.pendingEntries.concat(entries);
this.process();
};

process = () => {
const scheduled = this.pendingEntries.splice(0, this.concurrency - this.inFlight);
this.inFlight += scheduled.length;
scheduled.forEach(async task => {
try {
await this.worker(task);
} catch (err) {
this.err = err;
} finally {
this.inFlight -= 1;
}

if (this.pendingEntries.length > 0) {
this.process();
}
});
};

wait = (options = {}) => {
return waitUntil(
() => {
if (this.err) {
this.pendingEntries = [];
throw this.err;
}

return {
predicate: options.empty
? this.inFlight === 0 && this.pendingEntries.length === 0
: this.concurrency > this.pendingEntries.length,
};
},
{
delay: 50,
},
);
};
}

export default Queue;
3 changes: 3 additions & 0 deletions modules/waterfall/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Waterfall

A set of utility functions for handling async/await at scale.
8 changes: 8 additions & 0 deletions modules/waterfall/forEach.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
async function forEach(array, iteratee) {
for (let i = 0; i < array.length; i += 1) {
// eslint-disable-next-line no-await-in-loop
await iteratee(array[i], i);
}
}

export default forEach;
126 changes: 126 additions & 0 deletions modules/waterfall/metric.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// The API is inspired by console.time
// The implementation is isomorphic.
import warning from 'warning';

const times = new Map();

const implementations = {
mark: {
start: name => {
times.set(name, performance.now());
performance.mark(`metric_${name}_start`);
},
end: name => {
const endMark = `metric_${name}_end`;
performance.mark(endMark);
const startMark = `metric_${name}_start`;
performance.measure(name, startMark, endMark);
const duration = performance.getEntriesByName(name)[0].duration;
return duration;
},
},
now: {
start: name => {
times.set(name, performance.now());
},
end: name => {
const time = times.get(name);
const duration = performance.now() - time;
return duration;
},
},
hrtime: {
start: name => {
// https://nodejs.org/api/process.html#process_process_hrtime_time
times.set(name, process.hrtime());
},
end: name => {
const time = times.get(name);
const durations = process.hrtime(time);
const duration = durations[0] / 1e3 + durations[1] / 1e6;
return duration;
},
},
};

let getImplementationCache;

function getImplementation() {
if (getImplementationCache) {
return getImplementationCache;
}

if (typeof performance !== 'undefined' && performance.mark) {
getImplementationCache = implementations.mark;
} else if (typeof performance !== 'undefined' && performance.now) {
getImplementationCache = implementations.now;
} else if (process.hrtime) {
getImplementationCache = implementations.hrtime;
} else {
throw new Error('No performance API available');
}

return getImplementationCache;
}

class Metric {
/**
* Call to begin a measurement.
*/
static start(name) {
warning(!times.get(name), 'Recording already started');
getImplementation().start(name);
}

/**
* Returns the duration of the timing metric. The unit is milliseconds.
* @type {number}
*/
static end(name) {
if (!times.get(name)) {
throw new Error(`No such name '${name}' for metric`);
}

const duration = getImplementation().end(name);
times.delete(name);
return duration;
}

name = '';

/**
* @param {string} name A name for the metric.
*/
constructor(name) {
if (!name) {
throw new Error('Please provide a metric name');
}

this.name = name;
}

/**
* Call to begin a measurement.
*/
start(name) {
if (name) {
throw new Error('The name argument is not supported');
}

Metric.start(this.name);
}

/**
* Returns the duration of the timing metric. The unit is milliseconds.
* @type {number}
*/
end(name) {
if (name) {
throw new Error('The name argument is not supported');
}

return Metric.end(this.name);
}
}

export default Metric;
34 changes: 34 additions & 0 deletions modules/waterfall/retry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Inspired by https://github.com/zeit/async-retry
// Without the retry dependency (1 kB gzipped +)
async function retry(tryFunction, options = {}) {
const { retries = 3 } = options;

let tries = 0;
let output = null;
let exitErr = null;

const bail = err => {
exitErr = err;
};

while (tries < retries) {
tries += 1;
try {
// eslint-disable-next-line no-await-in-loop
output = await tryFunction({ tries, bail });
break;
} catch (err) {
if (tries >= retries) {
throw err;
}
}
}

if (exitErr) {
throw exitErr;
}

return output;
}

export default retry;
Loading