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

Options UI #135

Merged
merged 62 commits into from
Sep 5, 2018
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
8403db5
Move gzipped size calculations into a worker and wrap it up in a `<Gz…
developit Aug 10, 2018
9ecbfb6
A couple tweaks for the app welcome (drop files) screen. We don't hav…
developit Aug 10, 2018
522279a
Prettier "pop" effect and styling for the drop zone/indicator.
developit Aug 10, 2018
388075b
Styling for the quantization toggle to make it look like a disclosure…
developit Aug 10, 2018
abc73c7
Add controls bar (zoom in/out/to, background toggle). @todo: extract …
developit Aug 10, 2018
a4a3cb8
When clicking/tapping the image area, give it focus.
developit Aug 10, 2018
89c82d6
Utilities used by this PR
developit Aug 10, 2018
3a36252
Add a `two-up-handle` attribute to the handle for easier styling (cla…
developit Aug 10, 2018
dd72202
Add a dummy comment to test netlify deploy
surma Aug 10, 2018
eef6353
Remove commented-out code.
developit Aug 10, 2018
5a622c8
Fix styling of vertical split (which as it turns out is slightly diff…
developit Aug 10, 2018
aa0d262
Use a composited overlay for the dark background instead of animating…
developit Aug 10, 2018
f32ac8f
Move grayscale styling into `<two-up>` by default, then set colors vi…
developit Aug 10, 2018
4b31b37
Remove commented-out svg fill
developit Aug 10, 2018
99776d1
Remove dummy comment
developit Aug 10, 2018
d17d94e
Change `<GzipSize>` to be `<FileSize>`, add `compress` option that le…
developit Aug 10, 2018
8d9f0c2
Dependency updates
developit Aug 10, 2018
c6ef9e9
Remove color animations from dnd overlay
developit Aug 10, 2018
1bcf82c
Don't use a cyclical import for EncodedImage, instead just specify th…
developit Aug 10, 2018
f195797
Pass source image through to FileSize component so it can compute delta
developit Aug 10, 2018
65e0a5f
Stylize size display with colors based on delta amount/direction
developit Aug 10, 2018
f711b1e
Remove box-shadow animation.
developit Aug 10, 2018
a96d1c5
Merge branch 'master' into ui
developit Aug 10, 2018
bbbeb10
Simplify font stack
developit Aug 16, 2018
31dfdbe
Remove commented out code
developit Aug 16, 2018
117eb80
Remove gzip compression from size component
developit Aug 16, 2018
d76e6c5
Remove memoization bits
developit Aug 16, 2018
b95621b
Use specific flattend props instead of passing large context objects …
developit Aug 16, 2018
ac870d4
Remove unused packages.
developit Aug 16, 2018
4d94cc8
Remove unreachable String case in FileSize, and omit redundant File type
developit Aug 16, 2018
163219a
Simplify calculateSize()
developit Aug 16, 2018
e1fbd2c
Fix types for FileSize!
developit Aug 16, 2018
cf98b7a
Remove FileSize title
developit Aug 16, 2018
385d61b
Make delta variable consistent.
developit Aug 16, 2018
31fc90b
Skip passing compareTo value for original image
developit Aug 16, 2018
bcce5a2
Remove manual focus
developit Aug 16, 2018
d83f845
Fix whitespace
developit Aug 16, 2018
d2da8d9
remove unused keyframes
developit Aug 16, 2018
cef8b4c
remove pointless flex-wrap property
developit Aug 16, 2018
06b2fa9
Remove unused resetZoom() method
developit Aug 16, 2018
8ae382f
Remove pointless flex properties
developit Aug 16, 2018
e962f89
Use `on` prefix for event handling
developit Aug 16, 2018
5838703
Remove pointless justify-self property
developit Aug 16, 2018
5109598
Use an inline SVG for TwoUp's handle icon so it can be colored from o…
developit Aug 16, 2018
ac87c64
Move orientation state up from `<Output>` into `<App>` and share it w…
developit Aug 16, 2018
14ee88f
Make the options panels responsive :)
developit Aug 16, 2018
6ad9d05
Show a plus sign for size increases `(+8%)`
developit Aug 16, 2018
8768212
Use inline SVG for the zoom +/- icons, collect SVG icons into one fil…
developit Aug 16, 2018
aa98359
Fix top/bottom options panels being reversed
developit Aug 16, 2018
0055bf2
remove commented out code
developit Aug 20, 2018
096a4e4
lockfile
developit Aug 20, 2018
8b106a8
Revert quanitzation toggle styles so it's just a checkbox.
developit Aug 20, 2018
e11122b
Remove minimum delta for compare size
developit Aug 20, 2018
2ef8ddb
Rename data prop to file.
developit Aug 20, 2018
e7af112
scale int -> float
developit Aug 20, 2018
78b7197
remove tabIndex
developit Aug 20, 2018
9f19f0e
Merge master
developit Aug 28, 2018
cedfc75
Remove old icon files
developit Aug 28, 2018
152aad9
Add width to options panels
developit Sep 4, 2018
df537ca
Add vertical scrolling when options are taller than 80% of the screen…
developit Sep 4, 2018
da9d99a
Merge branch 'ui' of github.com:GoogleChromeLabs/squoosh into ui
developit Sep 4, 2018
48cc475
Resolving conflicts
jakearchibald Sep 5, 2018
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: 0 additions & 4 deletions global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ declare namespace JSX {
interface IntrinsicElements { }
}

declare module 'preact-i18n';
declare module 'preact-material-components-drawer';
declare module 'material-radial-progress';

declare module 'classnames' {
export default function classnames(...args: any[]): string;
}
1,640 changes: 52 additions & 1,588 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"devDependencies": {
"@types/node": "^9.6.23",
"@types/pretty-bytes": "^5.1.0",
"@types/webassembly-js-api": "0.0.1",
"babel-loader": "^7.1.5",
"babel-plugin-jsx-pragmatic": "^1.0.2",
Expand Down Expand Up @@ -62,15 +63,10 @@
"webpack-plugin-replace": "^1.1.1"
},
"dependencies": {
"@types/filesize": "^3.6.0",
"classnames": "^2.2.6",
"comlink": "^3.0.3",
"comlink-loader": "^1.0.0",
"filesize": "^3.6.1",
"material-components-web": "^0.32.0",
"preact": "^8.3.1",
"preact-i18n": "^1.2.2",
"preact-material-components": "^1.4.7",
"preact-router": "^2.6.1"
"pretty-bytes": "^5.1.0"
}
}
53 changes: 31 additions & 22 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { h, Component } from 'preact';
import { partial } from 'filesize';

import { bind, linkRef, bitmapToImageData } from '../../lib/util';
import * as style from './style.scss';
Expand Down Expand Up @@ -37,6 +36,8 @@ import {
import { decodeImage } from '../../codecs/decoders';
import { cleanMerge, cleanSet } from '../../lib/clean-modify';

type Orientation = 'horizontal' | 'vertical';

interface SourceImage {
file: File;
bmp: ImageBitmap;
Expand Down Expand Up @@ -64,14 +65,13 @@ interface State {
images: [EncodedImage, EncodedImage];
loading: boolean;
error?: string;
orientation: Orientation;
}

interface UpdateImageOptions {
skipPreprocessing?: boolean;
}

const filesize = partial({});

async function preprocessImage(
source: SourceImage,
preprocessData: PreprocessorState,
Expand Down Expand Up @@ -113,6 +113,8 @@ async function compressImage(
}

export default class App extends Component<Props, State> {
widthQuery = window.matchMedia('(min-width: 500px)');

state: State = {
loading: false,
images: [
Expand All @@ -131,6 +133,7 @@ export default class App extends Component<Props, State> {
loading: false,
},
],
orientation: this.widthQuery.matches ? 'horizontal' : 'vertical',
};

private snackbar?: SnackBarElement;
Expand All @@ -146,6 +149,13 @@ export default class App extends Component<Props, State> {
window.STATE = this.state;
};
}

this.widthQuery.addListener(this.onMobileWidthChange);
}

@bind
onMobileWidthChange() {
this.setState({ orientation: this.widthQuery.matches ? 'horizontal' : 'vertical' });
}

onEncoderTypeChange(index: 0 | 1, newType: EncoderType): void {
Expand Down Expand Up @@ -287,33 +297,32 @@ export default class App extends Component<Props, State> {
this.snackbar.showSnackbar({ message: error });
}

render({ }: Props, { loading, images }: State) {
render({ }: Props, { loading, images, source, orientation }: State) {
const [leftImageBmp, rightImageBmp] = images.map(i => i.bmp);
const anyLoading = loading || images.some(image => image.loading);

return (
<file-drop accept="image/*" onfiledrop={this.onFileDrop}>
<div id="app" class={style.app}>
<div id="app" class={`${style.app} ${style[orientation]}`}>
{(leftImageBmp && rightImageBmp) ? (
<Output leftImg={leftImageBmp} rightImg={rightImageBmp} />
<Output
orientation={orientation}
leftImg={leftImageBmp}
rightImg={rightImageBmp}
/>
) : (
<div class={style.welcome}>
<h1>Select an image</h1>
<input type="file" onChange={this.onFileChange} />
</div>
)}
{images.map((image, index) => (
<span class={index ? style.rightLabel : style.leftLabel}>
{encoderMap[image.encoderState.type].label}
{(image.downloadUrl && image.file) && (
<a href={image.downloadUrl} download={image.file.name}>🔻</a>
)}
{image.file && ` - ${filesize(image.file.size)}`}
</span>
))}
{images.map((image, index) => (
<div class={style.welcome}>
<h1>Drop, paste or select an image</h1>
<input type="file" onChange={this.onFileChange} />
</div>
)}
{(leftImageBmp && rightImageBmp) && images.map((image, index) => (
<Options
class={index ? style.rightOptions : style.leftOptions}
orientation={orientation}
imageIndex={index}
imageFile={image.file}
sourceImageFile={source && source.file}
downloadUrl={image.downloadUrl}
preprocessorState={image.preprocessorState}
encoderState={image.encoderState}
onEncoderTypeChange={this.onEncoderTypeChange.bind(this, index)}
Expand Down
82 changes: 44 additions & 38 deletions src/components/App/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,74 +10,80 @@ Note: These styles are temporary. They will be replaced before going live.
height: 100%;
overflow: hidden;
contain: strict;
display: flex;
justify-content: flex-end;

.leftLabel,
.rightLabel {
position: fixed;
bottom: 0;
padding: 5px 10px;
background: rgba(0,0,0,0.5);
color: #fff;
&.horizontal {
justify-content: space-between;
align-items: flex-end;
}

.leftLabel { left: 0; }
.rightLabel { right: 0; }

.leftOptions,
.rightOptions {
position: fixed;
bottom: 40px;
&.vertical {
flex-direction: column;
}

.leftOptions { left: 10px; }
.rightOptions { right: 10px; }
}

.welcome {
position: absolute;
display: inline-block;
left: 50%;
top: 50%;
padding: 20px;
transform: translate(-50%, -50%);
margin: auto;
text-align: center;

h1 {
font-weight: inherit;
font-size: 150%;
text-align: center;
}

input {
display: inline-block;
width: 16em;
padding: 5px;
padding: 10px;
margin: 0 auto;
-webkit-appearance: none;
border: 1px solid #b68c86;
background: #f0d3cf;
box-shadow: inset 0 0 1px #fff;
border: 1px solid var(--button-fg);
background: rgba(var(--button-fg-color), 0.1);
border-radius: 3px;
cursor: pointer;
}
}

:global {
:global {
file-drop {
overflow: hidden;
touch-action: none;
height:100%;
width:100%;

&.drop-valid {
transition: opacity 200ms ease-in-out, background-color 200ms;
opacity: 0.5;
background-color:green;
&:after {
content: '';
position: absolute;
display: block;
left: 10px;
top: 10px;
right: 10px;
bottom: 10px;
border: 2px dashed #fff;
border-radius: 10px;
opacity: 0;
transform: scale(0.95);
transition: opacity 300ms ease, transform 300ms cubic-bezier(.6,2,.6,1), background-color 300ms step-end, border-color 300ms step-end;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't animate anything that involves layouts or paints unless we have no alternative. Are we currently using drop-valid and drop-invalid? I don't think we can detect that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, it looks like the background-color and border-color animations are removed in cases that the background or border actually changes.

Copy link
Collaborator Author

@developit developit Aug 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm - maybe try it out? Without the step animation, the overlay's "exit" animation changes to the wrong color immediately. Are stepped transitions still problematic for jank? It doesn't seem like they should be.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh gotcha. I misinterpreted this. We might drop the colours for drop valid/invalid (we can't properly tell what's valid or not anyay), but that's for another PR.

pointer-events: none;
}

&.drop-invalid {
transition: opacity 200ms ease-in-out, background-color 200ms;
opacity: 0.5;
background-color:red;
&.drop-valid:after,
&.drop-invalid:after {
opacity: 1;
transform: scale(1);
transition: opacity 300ms ease, transform 300ms cubic-bezier(.6,2,.6,1);
}

&.drop-valid:after {
background-color:rgba(88, 116, 88, 0.2);
border-color: rgba(65, 129, 65, 0.5);
}

&.drop-invalid:after {
background-color:rgba(119, 85, 85, 0.2);
border-color:rgba(129, 63, 63, 0.5);
}
}
}
}
87 changes: 87 additions & 0 deletions src/components/FileSize.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { h, Component } from 'preact';
import * as prettyBytes from 'pretty-bytes';

type FileContents = ArrayBuffer | Blob;

interface Props extends Pick<JSX.HTMLAttributes, Exclude<keyof JSX.HTMLAttributes, 'data'>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be simpler to just rename data rather than messing with types?

Copy link
Collaborator Author

@developit developit Aug 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Yes. I original renamed it to file. Preferable?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that seems fine

file?: FileContents;
compareTo?: FileContents;
increaseClass?: string;
decreaseClass?: string;
}

interface State {
size?: number;
sizeFormatted?: string;
compareSize?: number;
compareSizeFormatted?: string;
}

function calculateSize(data: FileContents): number {
return data instanceof ArrayBuffer ? data.byteLength : data.size;
}

export default class FileSize extends Component<Props, State> {
constructor(props: Props) {
super(props);
if (props.file) {
this.computeSize('size', props.file);
}
if (props.compareTo) {
this.computeSize('compareSize', props.compareTo);
}
}

componentWillReceiveProps({ file, compareTo }: Props) {
if (file !== this.props.file) {
this.computeSize('size', file);
}
if (compareTo !== this.props.compareTo) {
this.computeSize('compareSize', compareTo);
}
}

componentDidMount() {
this.applyStyles();
}

componentDidUpdate() {
this.applyStyles();
}

applyStyles() {
const { size, compareSize = 0 } = this.state;
if (size != null && this.base) {
const delta = size && compareSize ? (size - compareSize) / compareSize : 0;
this.base.style.setProperty('--size', '' + size);
this.base.style.setProperty('--size-delta', '' + Math.round(Math.abs(delta * 100)));
}
}

computeSize(prop: keyof State, data?: FileContents) {
const size = data ? calculateSize(data) : 0;
const pretty = prettyBytes(size);
this.setState({
[prop]: size,
[prop + 'Formatted']: pretty,
});
}

render(
{ file, compareTo, increaseClass, decreaseClass, ...props }: Props,
{ size, sizeFormatted = '', compareSize }: State,
) {
const delta = size && compareSize ? (size - compareSize) / compareSize : 0;
return (
<span {...props}>
{sizeFormatted}
{compareTo && (
<span class={delta > 0 ? increaseClass : decreaseClass}>
{delta > 0 && '+'}
{Math.round(delta * 100)}%
</span>
)}
</span>
);
}
}
Loading