mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-12 00:37:19 +00:00
interim commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/*.log
|
||||||
15965
package-lock.json
generated
Normal file
15965
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
package.json
Normal file
40
package.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"name": "squoosh",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "apache-2.0",
|
||||||
|
"scripts": {
|
||||||
|
"start": "if-env NODE_ENV=production && npm run -s serve || npm run -s dev",
|
||||||
|
"build": "preact build",
|
||||||
|
"serve": "preact build && preact serve",
|
||||||
|
"dev": "preact watch",
|
||||||
|
"lint": "eslint src"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "eslint-config-developit",
|
||||||
|
"rules": {
|
||||||
|
"react/prefer-stateless-function": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslintIgnore": [
|
||||||
|
"build/*"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^4.18.2",
|
||||||
|
"eslint-config-developit": "^1.1.1",
|
||||||
|
"if-env": "^1.0.4",
|
||||||
|
"node-sass": "^4.7.2",
|
||||||
|
"preact-cli": "^2.2.1",
|
||||||
|
"sass-loader": "^6.0.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"material-components-web": "^0.31.0",
|
||||||
|
"material-radial-progress": "git+https://gist.github.com/02134901c77c5309924bfcf8b4435ebe.git",
|
||||||
|
"preact": "^8.2.7",
|
||||||
|
"preact-compat": "^3.18.0",
|
||||||
|
"preact-i18n": "^1.2.0",
|
||||||
|
"preact-material-components": "^1.3.7",
|
||||||
|
"preact-material-components-drawer": "git+https://gist.github.com/a78fceed440b98e62582e4440b86bfab.git",
|
||||||
|
"preact-router": "^2.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/assets/favicon.ico
Normal file
BIN
src/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/icon.png
Normal file
BIN
src/assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
36
src/components/app/index.js
Normal file
36
src/components/app/index.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
import { updater, toggle } from '../../lib/util';
|
||||||
|
import Fab from '../fab';
|
||||||
|
import Header from '../header';
|
||||||
|
import Drawer from '../drawer';
|
||||||
|
import Home from '../home';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
export default class App extends Component {
|
||||||
|
state = {
|
||||||
|
showDrawer: false,
|
||||||
|
showFab: true
|
||||||
|
};
|
||||||
|
|
||||||
|
openDrawer = updater(this, 'showDrawer', true);
|
||||||
|
closeDrawer = updater(this, 'showDrawer', false);
|
||||||
|
toggleDrawer = updater(this, 'showDrawer', toggle);
|
||||||
|
|
||||||
|
openFab = updater(this, 'showFab', true);
|
||||||
|
closeFab = updater(this, 'showFab', false);
|
||||||
|
toggleFab = updater(this, 'showFab', toggle);
|
||||||
|
|
||||||
|
render({ url }, { showDrawer, showFab }) {
|
||||||
|
return (
|
||||||
|
<div id="app" class={style.app}>
|
||||||
|
<Fab showing={showFab} />
|
||||||
|
<Header toggleDrawer={this.toggleDrawer} />
|
||||||
|
<Drawer showing={showDrawer} openDrawer={this.openDrawer} closeDrawer={this.closeDrawer} />
|
||||||
|
<div class={style.content} paint-outside>
|
||||||
|
<Home />
|
||||||
|
</div>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/components/app/style.scss
Normal file
21
src/components/app/style.scss
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@import '~style/helpers.scss';
|
||||||
|
|
||||||
|
.app {
|
||||||
|
position: absolute;
|
||||||
|
top: $toolbar-height;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
contain: size layout style;
|
||||||
|
overflow: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/components/drawer/index.js
Normal file
38
src/components/drawer/index.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
import MdlDrawer from 'preact-material-components-drawer';
|
||||||
|
import 'preact-material-components/Drawer/style.css';
|
||||||
|
import List from 'preact-material-components/List';
|
||||||
|
// import 'preact-material-components/List/style.css';
|
||||||
|
import { Text } from 'preact-i18n';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
export default class Drawer extends Component {
|
||||||
|
render({ showing, openDrawer, closeDrawer }) {
|
||||||
|
return (
|
||||||
|
<MdlDrawer open={showing} onOpen={openDrawer} onClose={closeDrawer}>
|
||||||
|
<MdlDrawer.Header autosize class="mdc-theme--primary-bg">
|
||||||
|
<img class={style.logo} alt="logo" src="/assets/icon.png" />
|
||||||
|
</MdlDrawer.Header>
|
||||||
|
<MdlDrawer.Content autosize class={style.list}>
|
||||||
|
<List autosize>
|
||||||
|
<List.LinkItem href="/">
|
||||||
|
<List.ItemIcon>verified_user</List.ItemIcon>
|
||||||
|
<Text id="SIGN_IN">Sign In</Text>
|
||||||
|
</List.LinkItem>
|
||||||
|
<List.LinkItem href="/register">
|
||||||
|
<List.ItemIcon>account_circle</List.ItemIcon>
|
||||||
|
<Text id="REGISTER">Register</Text>
|
||||||
|
</List.LinkItem>
|
||||||
|
</List>
|
||||||
|
</MdlDrawer.Content>
|
||||||
|
|
||||||
|
<div class={style.bottom} autosize>
|
||||||
|
<List.LinkItem href="/preferences">
|
||||||
|
<List.ItemIcon>settings</List.ItemIcon>
|
||||||
|
<Text id="PREFERENCES">Preferences</Text>
|
||||||
|
</List.LinkItem>
|
||||||
|
</div>
|
||||||
|
</MdlDrawer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/components/drawer/style.scss
Normal file
29
src/components/drawer/style.scss
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
@import '~style/helpers.scss';
|
||||||
|
|
||||||
|
:global {
|
||||||
|
// @import '~preact-material-components/Drawer/style.css';
|
||||||
|
@import '~preact-material-components/List/mdc-list.scss';
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer {
|
||||||
|
:global(.mdc-list-item__start-detail) {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category img {
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
bottom: constant(safe-area-inset-bottom);
|
||||||
|
bottom: env(safe-area-inset-bottom);
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
28
src/components/fab/index.js
Normal file
28
src/components/fab/index.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
import Icon from 'preact-material-components/Icon';
|
||||||
|
import 'preact-material-components/Icon/style.css';
|
||||||
|
import Fab from 'preact-material-components/Fab';
|
||||||
|
import RadialProgress from 'material-radial-progress';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
export default class AppFab extends Component {
|
||||||
|
handleClick = () => {
|
||||||
|
console.log('TODO: Save the file to disk.');
|
||||||
|
this.setState({ loading: true });
|
||||||
|
setTimeout( () => {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}, 100000);
|
||||||
|
};
|
||||||
|
|
||||||
|
render({}, { loading }) {
|
||||||
|
return (
|
||||||
|
<Fab ripple secondary class={style.fab} onClick={this.handleClick}>
|
||||||
|
{ loading ? (
|
||||||
|
<RadialProgress primary class={style.progress} />
|
||||||
|
) : (
|
||||||
|
<Icon autosize>file_download</Icon>
|
||||||
|
) }
|
||||||
|
</Fab>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/components/fab/style.scss
Normal file
18
src/components/fab/style.scss
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
@import '~style/helpers.scss';
|
||||||
|
:global {
|
||||||
|
@import '~preact-material-components/Fab/mdc-fab.scss';
|
||||||
|
}
|
||||||
|
|
||||||
|
.fab {
|
||||||
|
position: fixed;
|
||||||
|
right: 14px;
|
||||||
|
bottom: 14px;
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: white;
|
||||||
|
--mdc-theme-primary: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/components/header/index.js
Normal file
35
src/components/header/index.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
import Toolbar from 'preact-material-components/Toolbar';
|
||||||
|
// import 'preact-material-components/Toolbar/mdc-toolbar.scss';
|
||||||
|
// import Icon from 'preact-material-components/Icon';
|
||||||
|
// import 'preact-material-components/Icon/style.css';
|
||||||
|
// import Fab from 'preact-material-components/Fab';
|
||||||
|
// import 'preact-material-components/Fab/mdc-fab.scss';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
export default class Header extends Component {
|
||||||
|
// fabClick = () => {
|
||||||
|
// alert("Hello");
|
||||||
|
// };
|
||||||
|
|
||||||
|
render({ toggleDrawer, showHeader, showFab }) {
|
||||||
|
return (
|
||||||
|
<Toolbar class={`${style.toolbar} ${showHeader === false ? style.minimal : ''} inert`} fixed>
|
||||||
|
<Toolbar.Row>
|
||||||
|
<Toolbar.Title autosize class={style.title}>
|
||||||
|
<img class={style.logo} src="/assets/icon.png" />
|
||||||
|
</Toolbar.Title>
|
||||||
|
<Toolbar.Section autosize align-end>
|
||||||
|
<Toolbar.Icon autosize menu onClick={toggleDrawer}>menu</Toolbar.Icon>
|
||||||
|
</Toolbar.Section>
|
||||||
|
</Toolbar.Row>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Fab class={style.fab} exited={showFab===false} ripple onClick={this.fabClick}>
|
||||||
|
<Icon>create</Icon>
|
||||||
|
</Fab>
|
||||||
|
*/}
|
||||||
|
</Toolbar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/components/header/style.scss
Normal file
45
src/components/header/style.scss
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
@import '~style/helpers.scss';
|
||||||
|
:global {
|
||||||
|
@import '~preact-material-components/Toolbar/mdc-toolbar.scss';
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
height: $toolbar-height;
|
||||||
|
|
||||||
|
&.minimal {
|
||||||
|
height: $toolbar-height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// > * {
|
||||||
|
// min-height: 0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
.fab {
|
||||||
|
position: fixed;
|
||||||
|
display: block;
|
||||||
|
right: 14px;
|
||||||
|
bottom: 14px;
|
||||||
|
// z-index: 999;
|
||||||
|
// transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
position: absolute;
|
||||||
|
top: $toolbar-height;
|
||||||
|
right: 5px;
|
||||||
|
|
||||||
|
.menuItem {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 3px 0 0;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 140%;
|
||||||
|
}
|
||||||
16
src/components/home/index.js
Normal file
16
src/components/home/index.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
// import Button from 'preact-material-components/Button';
|
||||||
|
// import Switch from 'preact-material-components/Switch';
|
||||||
|
// import 'preact-material-components/Switch/style.css';
|
||||||
|
import style from './style';
|
||||||
|
|
||||||
|
|
||||||
|
export default class Home extends Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div class={style.home}>
|
||||||
|
<h1>Home</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/components/home/style.scss
Normal file
10
src/components/home/style.scss
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@import '~style/helpers.scss';
|
||||||
|
|
||||||
|
// :global {
|
||||||
|
// @import '~preact-material-components/Button/mdc-button.scss';
|
||||||
|
// // @import '~preact-material-components/Switch/mdc-switch.scss';
|
||||||
|
// }
|
||||||
|
|
||||||
|
.home {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
18
src/index.js
Normal file
18
src/index.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import './style';
|
||||||
|
import './lib/fix-pmc';
|
||||||
|
import App from './components/app';
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
||||||
|
if (typeof window!=='undefined') {
|
||||||
|
addEventListener('click', e => {
|
||||||
|
let { target } = e;
|
||||||
|
do {
|
||||||
|
if (target.nodeName === 'A') {
|
||||||
|
history.pushState(null, null, target.pathname);
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (target = target.parentNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
26
src/lib/fix-pmc.js
Normal file
26
src/lib/fix-pmc.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { options } from 'preact';
|
||||||
|
|
||||||
|
const classNameDescriptor = {
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
get() {
|
||||||
|
return this.class;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.class = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let old = options.vnode;
|
||||||
|
options.vnode = vnode => {
|
||||||
|
let a = vnode.attributes;
|
||||||
|
if (a!=null) {
|
||||||
|
if ('className' in a) {
|
||||||
|
a.class = a.className;
|
||||||
|
}
|
||||||
|
if ('class' in a) {
|
||||||
|
Object.defineProperty(a, 'className', classNameDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (old != null) old(vnode);
|
||||||
|
};
|
||||||
10
src/lib/util.js
Normal file
10
src/lib/util.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export function updater(obj, property, value) {
|
||||||
|
return e => {
|
||||||
|
let update = {};
|
||||||
|
update[property] = typeof value === 'function' ? value(obj.state[property], e) : value;
|
||||||
|
obj.setState(update);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toggle = value => !value;
|
||||||
|
|
||||||
16
src/manifest.json
Normal file
16
src/manifest.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "Squoosh",
|
||||||
|
"short_name": "Squoosh",
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"background_color": "#fff",
|
||||||
|
"theme_color": "#673ab8",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/assets/icon.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
10
src/style/helpers.scss
Normal file
10
src/style/helpers.scss
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
$toolbar-height: 56px;
|
||||||
|
|
||||||
|
$mdc-theme-primary: #263238;
|
||||||
|
$mdc-theme-primary-light: #4f5b62;
|
||||||
|
$mdc-theme-primary-dark: #000a12;
|
||||||
|
$mdc-theme-secondary: #d81b60;
|
||||||
|
$mdc-theme-secondary-light: #ff5c8d;
|
||||||
|
$mdc-theme-secondary-dark: #a00037;
|
||||||
|
$mdc-theme-secondary-dark: #a00037;
|
||||||
|
$mdc-theme-background: #fff;
|
||||||
26
src/style/index.scss
Normal file
26
src/style/index.scss
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// @import './material-icons.scss';
|
||||||
|
// @import 'material-components-web/material-components-web';
|
||||||
|
@import './reset.scss';
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
background: #FAFAFA;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #444;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdc-theme--dark {
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
28
src/style/material-icons.scss
Normal file
28
src/style/material-icons.scss
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Material Icons';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Material Icons'),
|
||||||
|
local('MaterialIcons-Regular'),
|
||||||
|
url(https://example.com/MaterialIcons-Regular.woff2) format('woff2'),
|
||||||
|
url(https://example.com/MaterialIcons-Regular.woff) format('woff'),
|
||||||
|
url(https://example.com/MaterialIcons-Regular.ttf) format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-icons {
|
||||||
|
font-family: 'Material Icons';
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 24px;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
direction: ltr;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
font-feature-settings: 'liga';
|
||||||
|
}
|
||||||
12
src/style/reset.scss
Normal file
12
src/style/reset.scss
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
button, a, img, input, select, textarea {
|
||||||
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
a, button, img, [inert], .inert {
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-drag: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
touch-callout: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user