mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-16 02:29:50 +00:00
Adds an app skeleton. Still needs some work.
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
110
src/components/app/index.tsx
Normal file
110
src/components/app/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { h, Component } from 'preact';
|
||||
import { updater, toggle, When } from '../../lib/util';
|
||||
import Fab from '../fab';
|
||||
import Header from '../header';
|
||||
// import Drawer from 'async!../drawer';
|
||||
import Home from '../home';
|
||||
import * as style from './style.scss';
|
||||
|
||||
type Props = {
|
||||
url?: String
|
||||
}
|
||||
|
||||
type FileObj = {
|
||||
id: any,
|
||||
data: any,
|
||||
error: Error | DOMError | String,
|
||||
file: File,
|
||||
loading: Boolean
|
||||
};
|
||||
|
||||
type State = {
|
||||
showDrawer: Boolean,
|
||||
showFab: Boolean,
|
||||
files: FileObj[]
|
||||
};
|
||||
|
||||
let counter = 0;
|
||||
|
||||
export default class App extends Component<Props, State> {
|
||||
state: State = {
|
||||
showDrawer: false,
|
||||
showFab: true,
|
||||
files: []
|
||||
};
|
||||
|
||||
loadFile = (file: File) => {
|
||||
let fileObj = {
|
||||
id: ++counter,
|
||||
file,
|
||||
error: null,
|
||||
loading: true,
|
||||
data: null
|
||||
};
|
||||
|
||||
this.setState({
|
||||
files: [fileObj]
|
||||
});
|
||||
|
||||
let fr = new FileReader();
|
||||
// fr.readAsArrayBuffer();
|
||||
fr.onerror = () => {
|
||||
let files = this.state.files.slice();
|
||||
files.splice(0, files.indexOf(fileObj), {
|
||||
...fileObj,
|
||||
error: fr.error,
|
||||
loading: false
|
||||
});
|
||||
this.setState({ files });
|
||||
};
|
||||
fr.onloadend = () => {
|
||||
let files = this.state.files.slice();
|
||||
files.splice(0, files.indexOf(fileObj), {
|
||||
...fileObj,
|
||||
data: fr.result,
|
||||
loading: false
|
||||
});
|
||||
this.setState({ files });
|
||||
};
|
||||
fr.readAsDataURL(file);
|
||||
};
|
||||
|
||||
enableDrawer = false;
|
||||
|
||||
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, files }) {
|
||||
if (showDrawer) this.enableDrawer = true;
|
||||
return (
|
||||
<div id="app" class={style.app}>
|
||||
<Fab showing={showFab} />
|
||||
|
||||
<Header toggleDrawer={this.toggleDrawer} loadFile={this.loadFile} />
|
||||
|
||||
{/* Avoid loading & rendering the drawer until the first time it is shown. */}
|
||||
{/*
|
||||
<When value={showDrawer}>
|
||||
<Drawer showing={showDrawer} openDrawer={this.openDrawer} closeDrawer={this.closeDrawer} />
|
||||
</When>
|
||||
*/}
|
||||
|
||||
{/*
|
||||
Note: this is normally where a <Router> with auto code-splitting goes.
|
||||
Since we don't seem to need one (yet?), it's omitted.
|
||||
*/}
|
||||
<div class={style.content}>
|
||||
<Home files={files} />
|
||||
</div>
|
||||
|
||||
{/* This ends up in the body when prerendered, which makes it load async. */}
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
2
src/components/app/style.scss.d.ts
vendored
Normal file
2
src/components/app/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export const app: string;
|
||||
export const content: string;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component } from 'preact';
|
||||
import { h, Component } from 'preact';
|
||||
import MdlDrawer from 'preact-material-components-drawer';
|
||||
import 'preact-material-components/Drawer/style.css';
|
||||
import List from 'preact-material-components/List';
|
||||
@@ -7,14 +7,27 @@ import { Text } from 'preact-i18n';
|
||||
import style from './style';
|
||||
|
||||
export default class Drawer extends Component {
|
||||
render({ showing, openDrawer, closeDrawer }) {
|
||||
state = {
|
||||
rendered: false
|
||||
};
|
||||
|
||||
setRendered = () => {
|
||||
this.setState({ rendered: true });
|
||||
};
|
||||
|
||||
render({ showing, openDrawer, closeDrawer }, { rendered }) {
|
||||
if (showing && !rendered) {
|
||||
setTimeout(this.setRendered, 20);
|
||||
showing = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<MdlDrawer open={showing} onOpen={openDrawer} onClose={closeDrawer}>
|
||||
<MdlDrawer.Header autosize class="mdc-theme--primary-bg">
|
||||
<MdlDrawer.Header 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>
|
||||
<MdlDrawer.Content class={style.list}>
|
||||
<List>
|
||||
<List.LinkItem href="/">
|
||||
<List.ItemIcon>verified_user</List.ItemIcon>
|
||||
<Text id="SIGN_IN">Sign In</Text>
|
||||
@@ -26,7 +39,7 @@ export default class Drawer extends Component {
|
||||
</List>
|
||||
</MdlDrawer.Content>
|
||||
|
||||
<div class={style.bottom} autosize>
|
||||
<div class={style.bottom}>
|
||||
<List.LinkItem href="/preferences">
|
||||
<List.ItemIcon>settings</List.ItemIcon>
|
||||
<Text id="PREFERENCES">Preferences</Text>
|
||||
|
||||
14
src/components/drawer/style.scss.d.ts
vendored
Normal file
14
src/components/drawer/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
export const mdcListItemSecondaryText: string;
|
||||
export const mdcListItemGraphic: string;
|
||||
export const mdcListItemMeta: string;
|
||||
export const mdcListItem: string;
|
||||
export const mdcListDivider: string;
|
||||
export const mdcListGroup: string;
|
||||
export const mdcListGroupSubheader: string;
|
||||
export const drawer: string;
|
||||
export const logo: string;
|
||||
export const category: string;
|
||||
export const bottom: string;
|
||||
export const mdcRippleFgRadiusIn: string;
|
||||
export const mdcRippleFgOpacityIn: string;
|
||||
export const mdcRippleFgOpacityOut: string;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component } from 'preact';
|
||||
import { h, Component } from 'preact';
|
||||
import Icon from 'preact-material-components/Icon';
|
||||
import 'preact-material-components/Icon/style.css';
|
||||
import Fab from 'preact-material-components/Fab';
|
||||
@@ -20,7 +20,7 @@ export default class AppFab extends Component {
|
||||
{ loading ? (
|
||||
<RadialProgress primary class={style.progress} />
|
||||
) : (
|
||||
<Icon autosize>file_download</Icon>
|
||||
<Icon>file_download</Icon>
|
||||
) }
|
||||
</Fab>
|
||||
);
|
||||
|
||||
5
src/components/fab/style.scss.d.ts
vendored
Normal file
5
src/components/fab/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export const fab: string;
|
||||
export const progress: string;
|
||||
export const mdcRippleFgRadiusIn: string;
|
||||
export const mdcRippleFgOpacityIn: string;
|
||||
export const mdcRippleFgOpacityOut: string;
|
||||
@@ -1,34 +1,45 @@
|
||||
import { Component } from 'preact';
|
||||
import { h, 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 cx from 'classnames';
|
||||
import style from './style';
|
||||
|
||||
export default class Header extends Component {
|
||||
// fabClick = () => {
|
||||
// alert("Hello");
|
||||
// };
|
||||
setInputRef = c => {
|
||||
this.input = c;
|
||||
};
|
||||
|
||||
handleFiles = () => {
|
||||
let files = this.input.files;
|
||||
if (files.length) {
|
||||
this.props.loadFile(files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
upload = () => {
|
||||
// let input = document.createElement('input');
|
||||
// input.type = 'file';
|
||||
// // input.multiple = true;
|
||||
// document.body.appendChild(input);
|
||||
// input.addEventListener('change', e => {
|
||||
|
||||
// });
|
||||
// input.click();
|
||||
this.input.click();
|
||||
};
|
||||
|
||||
render({ toggleDrawer, showHeader, showFab }) {
|
||||
return (
|
||||
<Toolbar class={`${style.toolbar} ${showHeader === false ? style.minimal : ''} inert`} fixed>
|
||||
<Toolbar fixed class={cx(style.toolbar, 'inert', showHeader===false && style.minimal)}>
|
||||
<Toolbar.Row>
|
||||
<Toolbar.Title autosize class={style.title}>
|
||||
<Toolbar.Title class={style.title}>
|
||||
<img class={style.logo} src="/assets/icon.png" />
|
||||
<Toolbar.Icon ripple onClick={this.upload}>file_upload</Toolbar.Icon>
|
||||
</Toolbar.Title>
|
||||
<Toolbar.Section autosize align-end>
|
||||
<Toolbar.Icon autosize menu onClick={toggleDrawer}>menu</Toolbar.Icon>
|
||||
<Toolbar.Section align-end>
|
||||
<Toolbar.Icon ripple onClick={toggleDrawer}>menu</Toolbar.Icon>
|
||||
</Toolbar.Section>
|
||||
</Toolbar.Row>
|
||||
|
||||
{/*
|
||||
<Fab class={style.fab} exited={showFab===false} ripple onClick={this.fabClick}>
|
||||
<Icon>create</Icon>
|
||||
</Fab>
|
||||
*/}
|
||||
<input class={style.fileInput} ref={this.setInputRef} type="file" onChange={this.handleFiles} />
|
||||
</Toolbar>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
// }
|
||||
}
|
||||
|
||||
.fileInput {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -999px;
|
||||
}
|
||||
|
||||
.fab {
|
||||
position: fixed;
|
||||
display: block;
|
||||
|
||||
8
src/components/header/style.scss.d.ts
vendored
Normal file
8
src/components/header/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export const toolbar: string;
|
||||
export const minimal: string;
|
||||
export const fileInput: string;
|
||||
export const fab: string;
|
||||
export const logo: string;
|
||||
export const menu: string;
|
||||
export const menuItem: string;
|
||||
export const title: string;
|
||||
@@ -1,16 +0,0 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
36
src/components/home/index.tsx
Normal file
36
src/components/home/index.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { h, 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 * as style from './style.scss';
|
||||
|
||||
type Props = {
|
||||
files: {
|
||||
data: any
|
||||
}[]
|
||||
};
|
||||
type State = {
|
||||
active: boolean
|
||||
};
|
||||
|
||||
export default class Home extends Component<Props, State> {
|
||||
state: State = {
|
||||
active: false
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
setTimeout( () => {
|
||||
this.setState({ active: true });
|
||||
});
|
||||
}
|
||||
|
||||
render({ files }, { active }) {
|
||||
return (
|
||||
<div class={style.home+' '+(active ? style.active : '')}>
|
||||
{ files && files[0] && (
|
||||
<img src={files[0].data} />
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,14 @@
|
||||
|
||||
.home {
|
||||
padding: 20px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
animation: fadeIn 2s forwards ease 1;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
3
src/components/home/style.scss.d.ts
vendored
Normal file
3
src/components/home/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export const home: string;
|
||||
export const active: string;
|
||||
export const fadeIn: string;
|
||||
Reference in New Issue
Block a user