From 12f72e1740cd91929419c82c6b782393e306994c Mon Sep 17 00:00:00 2001 From: Eugen Date: Tue, 11 Apr 2017 00:38:58 +0200 Subject: When avatar/header are GIF, generate static versions (#1428) * When avatar/header are GIF, generate static versions. Account API returns "avatar"/"avatar_static", "header"/"header_static" Static version is the same as original for other cases Web UI de-animates avatars in toots, lists of users Fix #441, fix #596, prerequisite for #1064 * Fix JS test * Add rake task to generate static avatars/headers from GIF ones, add test --- .../javascripts/components/components/account.jsx | 2 +- .../javascripts/components/components/avatar.jsx | 135 ++++----------------- .../javascripts/components/components/status.jsx | 2 +- .../compose/components/autosuggest_account.jsx | 2 +- .../features/compose/components/navigation_bar.jsx | 2 +- .../compose/components/reply_indicator.jsx | 2 +- .../components/account_authorize.jsx | 2 +- .../features/status/components/detailed_status.jsx | 2 +- app/assets/stylesheets/components.scss | 10 +- 9 files changed, 37 insertions(+), 122 deletions(-) (limited to 'app/assets') diff --git a/app/assets/javascripts/components/components/account.jsx b/app/assets/javascripts/components/components/account.jsx index 7a1c9f5ce..782cf382d 100644 --- a/app/assets/javascripts/components/components/account.jsx +++ b/app/assets/javascripts/components/components/account.jsx @@ -65,7 +65,7 @@ const Account = React.createClass({
-
+
diff --git a/app/assets/javascripts/components/components/avatar.jsx b/app/assets/javascripts/components/components/avatar.jsx index 0237a1904..673b1a247 100644 --- a/app/assets/javascripts/components/components/avatar.jsx +++ b/app/assets/javascripts/components/components/avatar.jsx @@ -1,103 +1,18 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; -// From: http://stackoverflow.com/a/18320662 -const resample = (canvas, width, height, resize_canvas) => { - let width_source = canvas.width; - let height_source = canvas.height; - width = Math.round(width); - height = Math.round(height); - - let ratio_w = width_source / width; - let ratio_h = height_source / height; - let ratio_w_half = Math.ceil(ratio_w / 2); - let ratio_h_half = Math.ceil(ratio_h / 2); - - let ctx = canvas.getContext("2d"); - let img = ctx.getImageData(0, 0, width_source, height_source); - let img2 = ctx.createImageData(width, height); - let data = img.data; - let data2 = img2.data; - - for (let j = 0; j < height; j++) { - for (let i = 0; i < width; i++) { - let x2 = (i + j * width) * 4; - let weight = 0; - let weights = 0; - let weights_alpha = 0; - let gx_r = 0; - let gx_g = 0; - let gx_b = 0; - let gx_a = 0; - let center_y = (j + 0.5) * ratio_h; - let yy_start = Math.floor(j * ratio_h); - let yy_stop = Math.ceil((j + 1) * ratio_h); - - for (let yy = yy_start; yy < yy_stop; yy++) { - let dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half; - let center_x = (i + 0.5) * ratio_w; - let w0 = dy * dy; //pre-calc part of w - let xx_start = Math.floor(i * ratio_w); - let xx_stop = Math.ceil((i + 1) * ratio_w); - - for (let xx = xx_start; xx < xx_stop; xx++) { - let dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half; - let w = Math.sqrt(w0 + dx * dx); - - if (w >= 1) { - // pixel too far - continue; - } - - // hermite filter - weight = 2 * w * w * w - 3 * w * w + 1; - let pos_x = 4 * (xx + yy * width_source); - - // alpha - gx_a += weight * data[pos_x + 3]; - weights_alpha += weight; - - // colors - if (data[pos_x + 3] < 255) - weight = weight * data[pos_x + 3] / 250; - - gx_r += weight * data[pos_x]; - gx_g += weight * data[pos_x + 1]; - gx_b += weight * data[pos_x + 2]; - weights += weight; - } - } - - data2[x2] = gx_r / weights; - data2[x2 + 1] = gx_g / weights; - data2[x2 + 2] = gx_b / weights; - data2[x2 + 3] = gx_a / weights_alpha; - } - } - - // clear and resize canvas - if (resize_canvas === true) { - canvas.width = width; - canvas.height = height; - } else { - ctx.clearRect(0, 0, width_source, height_source); - } - - // draw - ctx.putImageData(img2, 0, 0); -}; - const Avatar = React.createClass({ propTypes: { src: React.PropTypes.string.isRequired, + staticSrc: React.PropTypes.string, size: React.PropTypes.number.isRequired, style: React.PropTypes.object, - animated: React.PropTypes.bool + animate: React.PropTypes.bool }, getDefaultProps () { return { - animated: true + animate: false }; }, @@ -117,38 +32,30 @@ const Avatar = React.createClass({ this.setState({ hovering: false }); }, - handleLoad () { - this.canvas.width = this.image.naturalWidth; - this.canvas.height = this.image.naturalHeight; - this.canvas.getContext('2d').drawImage(this.image, 0, 0); - - resample(this.canvas, this.props.size * window.devicePixelRatio, this.props.size * window.devicePixelRatio, true); - }, - - setImageRef (c) { - this.image = c; - }, - - setCanvasRef (c) { - this.canvas = c; - }, - render () { + const { src, size, staticSrc, animate } = this.props; const { hovering } = this.state; - if (this.props.animated) { - return ( -
- -
- ); + const style = { + ...this.props.style, + width: `${size}px`, + height: `${size}px`, + backgroundSize: `${size}px ${size}px` + }; + + if (hovering || animate) { + style.backgroundImage = `url(${src})`; + } else { + style.backgroundImage = `url(${staticSrc})`; } return ( -
- - -
+
); } diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx index 110d26c6d..65db8f79b 100644 --- a/app/assets/javascripts/components/components/status.jsx +++ b/app/assets/javascripts/components/components/status.jsx @@ -90,7 +90,7 @@ const Status = React.createClass({
- +
diff --git a/app/assets/javascripts/components/features/compose/components/autosuggest_account.jsx b/app/assets/javascripts/components/features/compose/components/autosuggest_account.jsx index 5591b45cf..9e05193fb 100644 --- a/app/assets/javascripts/components/features/compose/components/autosuggest_account.jsx +++ b/app/assets/javascripts/components/features/compose/components/autosuggest_account.jsx @@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; const AutosuggestAccount = ({ account }) => (
-
+
); diff --git a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx index 076ac7cbb..1a748a23c 100644 --- a/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx +++ b/app/assets/javascripts/components/features/compose/components/navigation_bar.jsx @@ -17,7 +17,7 @@ const NavigationBar = React.createClass({ render () { return (
- + diff --git a/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx b/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx index 1766655c2..9c713287c 100644 --- a/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx +++ b/app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx @@ -33,7 +33,7 @@ const AccountAuthorize = ({ intl, account, onAuthorize, onReject }) => {
-
+
diff --git a/app/assets/javascripts/components/features/status/components/detailed_status.jsx b/app/assets/javascripts/components/features/status/components/detailed_status.jsx index caa46ff3c..2da57252e 100644 --- a/app/assets/javascripts/components/features/status/components/detailed_status.jsx +++ b/app/assets/javascripts/components/features/status/components/detailed_status.jsx @@ -54,7 +54,7 @@ const DetailedStatus = React.createClass({ return (
-
+
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 95e432cb6..8c76ddf99 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -1,7 +1,7 @@ @import 'variables'; .app-body{ - -ms-overflow-style: -ms-autohiding-scrollbar; + -ms-overflow-style: -ms-autohiding-scrollbar; } .button { @@ -165,6 +165,14 @@ } } +.avatar { + border-radius: 4px; + background: transparent no-repeat; + background-position: 50%; + background-clip: padding-box; + position: relative; +} + .lightbox .icon-button { color: $color1; } -- cgit