diff --git a/package-lock.json b/package-lock.json index 582609b..3cd23da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10471,6 +10471,11 @@ } } }, + "web-animations-js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.1.tgz", + "integrity": "sha1-Om2bwVGWN3qQ+OKAP6UmIWWwRRA=" + }, "webauth": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/webauth/-/webauth-1.1.0.tgz", diff --git a/package.json b/package.json index 1ae90ff..822957f 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "testcafe": "^0.19.0", "timeago.js": "^3.0.2", "tiny-queue": "^0.2.1", + "web-animations-js": "^2.3.1", "webpack": "^4.1.0", "webpack-bundle-analyzer": "^2.11.1", "workerize-loader": "^1.0.1", @@ -100,7 +101,8 @@ "FormData", "atob", "btoa", - "Blob" + "Blob", + "Element" ], "ignore": [ "dist", diff --git a/routes/_components/IconButton.html b/routes/_components/IconButton.html index 332b250..dfeeac2 100644 --- a/routes/_components/IconButton.html +++ b/routes/_components/IconButton.html @@ -6,7 +6,7 @@ :disabled delegate-key="{{delegateKey}}" focus-key="{{focusKey || ''}}" > - + @@ -18,7 +18,7 @@ focus-key="{{focusKey || ''}}" :disabled on:click > - + @@ -50,7 +50,7 @@ } .icon-button.pressed .icon-button-svg { - fill: var(--action-button-fill-color-pressed) + fill: var(--action-button-fill-color-pressed); } .icon-button.pressed:hover .icon-button-svg { @@ -66,6 +66,16 @@ import { classname } from '../_utils/classname' export default { + oncreate() { + this.observe('animation', animation => { + if (!animation) { + return + } + let svg = this.refs.svg + let animations = animation.map(({properties, options}) => svg.animate(properties, options)) + animations.forEach(anim => anim.play()) + }) + }, computed: { computedClass: (pressable, pressed, big, className) => { return classname( diff --git a/routes/_components/status/StatusToolbar.html b/routes/_components/status/StatusToolbar.html index de55b0b..8997826 100644 --- a/routes/_components/status/StatusToolbar.html +++ b/routes/_components/status/StatusToolbar.html @@ -13,6 +13,7 @@ disabled="{{reblogDisabled}}" href="{{reblogIcon}}" delegateKey="{{reblogKey}}" + animation="{{animateReblog && reblogAnimation}}" /> ({ + favoriteAnimation: FAVORITE_ANIMATION, + reblogAnimation: REBLOG_ANIMATION + }), computed: { reblogLabel: (visibility) => { switch (visibility) { diff --git a/routes/_static/animations.js b/routes/_static/animations.js new file mode 100644 index 0000000..4fb2a80 --- /dev/null +++ b/routes/_static/animations.js @@ -0,0 +1,25 @@ +export const FAVORITE_ANIMATION = [ + { + properties: [ + {transform: 'scale(1)'}, + {transform: 'scale(2)'}, + {transform: 'scale(1)'} + ], + options: { + duration: 400, + easing: 'ease-in-out' + } + }, + { + properties: [ + {fill: 'var(--action-button-fill-color)'}, + {fill: 'var(--action-button-fill-color-pressed)'} + ], + options: { + duration: 400, + easing: 'linear' + } + } +] + +export const REBLOG_ANIMATION = FAVORITE_ANIMATION diff --git a/routes/_utils/asyncModules.js b/routes/_utils/asyncModules.js index e5aae72..4127f09 100644 --- a/routes/_utils/asyncModules.js +++ b/routes/_utils/asyncModules.js @@ -14,6 +14,10 @@ export const importIndexedDBGetAllShim = () => import( /* webpackChunkName: 'indexeddb-getall-shim' */ 'indexeddb-getall-shim' ) +export const importWebAnimationPolyfill = () => import( + /* webpackChunkName: 'web-animations-js' */ 'web-animations-js' + ) + export const importWebSocketClient = () => import( /* webpackChunkName: '@gamestdio/websocket' */ '@gamestdio/websocket' ).then(mod => mod.default) diff --git a/routes/_utils/loadPolyfills.js b/routes/_utils/loadPolyfills.js index 6bf27cc..9642c9d 100644 --- a/routes/_utils/loadPolyfills.js +++ b/routes/_utils/loadPolyfills.js @@ -1,13 +1,15 @@ import { importIntersectionObserver, importRequestIdleCallback, - importIndexedDBGetAllShim + importIndexedDBGetAllShim, + importWebAnimationPolyfill } from './asyncModules' export function loadPolyfills () { return Promise.all([ typeof IntersectionObserver === 'undefined' && importIntersectionObserver(), typeof requestIdleCallback === 'undefined' && importRequestIdleCallback(), - !IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim() + !IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim(), + !Element.prototype.animate && importWebAnimationPolyfill() ]) }